在下面的脚本中创建了一个简单的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()
答案 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
电话。
当您收到有关classobj
或instance
的错误消息时,您知道这种情况的方式(除了查看基类之外)。这两种类型总是意味着经典课程涉及到某个地方。
但等等,还有更多。
无论白痴告诉你如何将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()
答案 2 :(得分:0)