Python webserver脚本不会提交给sqlite3数据库

时间:2014-08-14 21:13:10

标签: python sqlite simplehttpserver

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

脚本的网络服务器部分正常运行。我在终端输出中看到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()

3 个答案:

答案 0 :(得分:2)

你错过了最后的魔术词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()

答案 1 :(得分:2)

首先你这样做:

httpd.serve_forever()

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

所以,你的代码在" forever"之前都没有做任何事情。等待它的时间太长了。

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

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

...而是这样做:

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

(或者只是去除额外的行并做httpd = SocketServer.TCPServer(("", PORT), DBLoggingHandler)。)

您还必须将班级定义移到文件顶部。


但还有另外一个问题。

Python曾经有两种不同的类:new-style and classic。他们多年前在3.0中修复过,但你还在使用2.something。

通常情况下,您可以随时使用新式类,而不用担心旧类,但每隔一段时间您就会遇到stdlib或第三方库中的一个类仍然是旧的方式,你想继承它。这就是这里发生的事情。所以,现在,遗憾的是,你必须了解旧式课程。

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

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

......你需要这个:

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

同样适用于其他super电话。

当您收到有关classobjinstance的错误消息时,您知道这种情况的方式(除了查看基类之外)。这两种类型总是意味着经典课程涉及到某个地方。


但等等,还有更多。

无论白痴告诉你如何将self.db = …方法放在__init__方法中,这是一个白痴。 :)

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

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


此外,您可能希望在某处关闭数据库。在不关闭数据库的情况下杀死程序应该永远不会让它损坏,但是如果你把时间错误的话,这可能意味着你输掉了最后一笔交易。

由于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()

答案 2 :(得分:0)

看看顶部的示例:

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

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