Python Web 服务器脚本不会提交到 sqlite3 数据库



在下面的脚本中创建了一个简单的web服务器,并且有一个类应该将GET数据发送到sqlite3数据库。

import SimpleHTTPServer
import SocketServer
import sqlite3
PORT = 8000
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "serving at port", PORT
httpd.serve_forever()

class DBLoggingHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super(DBLoggingHandler, self).__init__(*args, **kwargs)
        self.db = sqlite3.connect('/home/cron1admin/crazysean/crazysean.db')
    def do_GET(self):
        self.db.execute("INSERT INTO crazysean (command, vers, path) VALUES (?, ?, ?)",
                        (self.command, self.request_version, self.path))
        self.db.commit()
        return super(DBLoggingHandler, self).do_GET()
DBLoggingHandler()

脚本的webserver部分工作正常。我在终端输出中看到GET数据。但是,没有向我在db中创建的crazysean表写入任何内容。你认为我的脚本有什么问题,还是有其他问题?


代码已经更改,以反映我所做的更改,但它仍然没有写入数据库。

更新代码:

import SimpleHTTPServer
import SocketServer
import sqlite3
PORT = 8000
class DBLoggingHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)
        self.db = sqlite3.connect('/home/cron1admin/crazysean/crazysean.db')
    def do_GET(self):
        self.db.execute("INSERT INTO crazysean (command, vers, path) VALUES (?, ?, ?)",
                        (self.command, self.request_version, self.path))
        self.db.commit()
        return super(DBLoggingHandler, self).do_GET()
Handler = DBLoggingHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "serving at port", PORT
httpd.serve_forever()

首先这样做:

httpd.serve_forever()

然后创建处理程序类并实例化它。

所以,你的代码不会做任何事情,直到"永远"之后。等的时间太长了

您要做的是将处理程序子类传递给服务器,以代替基类。这里有:

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)

…改成这样:

Handler = DBLoggingHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)

(或者只是去掉多余的行并执行httpd = SocketServer.TCPServer(("", PORT), DBLoggingHandler)。)

您还必须将类的定义移到文件的顶部。


但是还有一个问题。

Python曾经有两种不同的类:new-style和classic。他们在几年前的3.0中修复了这个问题,但你仍然在使用2.something。

通常情况下,你可以总是使用新样式的类,而不必担心旧类型的类,但是每隔一段时间,你就会在标准库或第三方库中遇到一个仍然以旧方式制作的类,而你想要继承它。这就是这里发生的事情。所以,现在,遗憾的是,你必须学习老式的类。

旧式类不能做的事情是super。解决这个问题的方法是显式调用基类的未绑定方法。所以,不用这个:

super(DBLoggingHandler, self).__init__(*args, **kwargs)

…你需要这个:

SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)

对于其他super调用也是如此。

当你得到一个关于classobjinstance的错误消息时,你知道这正在发生(而不是通过查看基类)。这两种类型总是意味着某个地方涉及了一个经典类。


等等,还有呢

无论哪个白痴告诉你把self.db = …的东西放在__init__方法中都是白痴。:)

SocketServer处理程序是一种奇怪的类。每个新请求都构造一个新实例,__init__方法调用handle,直到销毁整个实例时才返回。因此,在调用基类之后放入__init__中的任何内容都不会发生,直到为时已晚。

这里最简单的事情可能是使db成为全局变量。在其他条件相同的情况下,全局变量很糟糕。但在这种情况下,替代方案似乎要么覆盖来自三个不同类的功能,要么将其monkeypatatch到服务器实例中,并依赖于未记录的细节来访问它。


另外,您可能希望在某个地方关闭数据库。在不关闭数据库的情况下终止程序应该不会使数据库损坏,但如果时间错误,则可能意味着丢失最后一个事务。

因为serve_forever永远不会返回,除非你按ctrl-c,你不能把它放在那行后面;您需要一个with语句(或finallyexcept BaseExceptionatexit)。我认为sqlite3.Connection对象直到Python的更高版本才成为上下文管理器,因此您将不得不使用closing上下文管理器。


:

import contextlib
import SimpleHTTPServer
import SocketServer
import sqlite3
PORT = 8000
db = sqlite3.connect('/home/cron1admin/crazysean/crazysean.db')
class DBLoggingHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_GET(self):
        db.execute("INSERT INTO crazysean (command, vers, path) VALUES (?, ?, ?)",
                        (self.command, self.request_version, self.path))
        db.commit()
        return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
Handler = DBLoggingHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "serving at port", PORT
with contextlib.closing(db):
    httpd.serve_forever()

你错过了最后的魔语db.commit():)

def do_GET(self):
        self.db.execute("INSERT INTO crazysean (command, vers, path) VALUES (?, ?, ?)",
                        (self.command, self.request_version, self.path))
        self.db.commit()
        return super(DBLoggingHandler, self).do_GET()

你有另一个错误,这个更大。你实际上没有调用你的代码,只是调用SimpleHTTPRequestHandler

完整的示例:

class DBLoggingHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(*args, **kwargs)
        self.db = sqlite3.connect('/home/cron1admin/crazysean/crazysean.db')
    def do_GET(self):
        self.db.execute("INSERT INTO crazysean (command, vers, path) VALUES (?, ?, ?)",
                        (self.command, self.request_version, self.path))
        self.db.commit()
        return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET()
Handler = DBLoggingHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "serving at port", PORT
httpd.serve_forever()

看一下顶部的例子:

https://docs.python.org/2/library/sqlite3.html

您需要创建一个游标,通过游标执行语句,然后提交连接

相关内容

  • 没有找到相关文章

最新更新