python webserver脚本不会提交到sqlite3数据库

2024-04-26 09:22:06 发布

您现在位置:Python中文网/ 问答频道 /正文

在下面的脚本中,创建了一个简单的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()

脚本的web服务器部分正常工作。我在终端输出中看到GET数据。但是,我在db中创建的crazysean表中没有写入任何内容。你觉得我的剧本有什么问题吗?还是可能是别的什么问题?在


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

更新代码:

^{pr2}$

Tags: 数据importself服务器脚本web数据库db
3条回答

您缺少最后的咒语^{}:)

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。在

完整示例:

^{pr2}$

首先你要这样做:

httpd.serve_forever()

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

所以,你的代码在“永远”之后才起作用。等它太久了。在

您要做的是将处理程序子类传递给服务器,而不是基类。如果你有这个:

^{pr2}$

…而是这样做:

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

(或者去掉多余的一行并做httpd = SocketServer.TCPServer(("", PORT), DBLoggingHandler

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


但还有另一个问题。在

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

通常,您可以一直使用新样式的类,而不必担心旧类,但是偶尔您会遇到stdlib或第三方库中仍然使用旧方法的类,并且您希望从中继承。这就是这里发生的事。所以现在,可悲的是,你必须学习旧式课程。在

旧样式类不能做的事情是super。解决方法是显式调用基类的unbound方法。所以,与其这样:

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

…你需要这个:

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

对于另一个super调用也是如此。在

您知道发生这种情况的方式(不是通过查看基类)是当您收到关于classobj或{}的错误消息时。这两种类型总是意味着某个地方涉及到一个经典类。在


等等,还有更多。在

不管白痴叫你把self.db = …的东西放到__init__方法中,都是白痴。:)

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

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


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

由于serve_forever永远不会返回,除非您按ctrl-c,所以不能将它放在该行之后;您需要一个with语句(或finally,或except BaseException,或atexit)。我不认为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()

请看下面的示例:

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

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

相关问题 更多 >