我编写了一个网络抓取工具,可以进行一些在线预处理并将数据存储到数据库中。数据库布局非常简单,但让我概述一下:
dispatched
列出了在特定时间调度的项目,这是其中一列。还有15个其他列描述了这些项:其中一列来自TEXT
类型,其余来自类型INT
。missed
列出了抓取工具无法观看的时间段,例如因为网络问题。它有INT
类型的4列和TEXT
类型的2列。我让它跑了两个小时。两次,生成的数据库文件的总大小恰好为256000字节,至少根据ls -l
。我从记录的数据中看到,每分钟定期记录1-3项,但从特定时间开始,不再列出任何新项目。
对我来说,这听起来好像我遇到了限制。鉴于生成的数据库文件大小两次都是1000 * 2^8
字节,我怀疑这是对最大数据库文件大小的限制,但documentation并没有这样说。
当SQLite停止向数据库添加新行时,有
dispatched
上的5187行和missed
上的3行dispatched
上的5212行和missed
上的2行。我正在使用Python {的sqlite3
模块。我感谢任何可能指出发生了什么的帮助,为什么SQLite在达到256000字节后停止追加新行以及如何解决这个问题。
更新:我已决定从我的代码中添加一些代码段。
应用程序包含由名为Gatherer
的类计划和执行的任务。首先,让我们看看这里感兴趣的任务:
class ControlTask(Task):
def __init__(self, player, scheduled_start):
Task.__init__(self, scheduled_start)
self.player = player
def __str__(self):
return u'CONTROL: player %d' % self.player.player_id
def execute(self, gt):
# [...]
gt.dispatch(self.player)
# [...]
当时间到来时,Gatherer
会在每项任务上调用execute
,通过gt
参数提供对自身的引用:
class Gatherer:
def process_next_task(self):
task = self.tasks.get()
while True:
即使在SQLite停止追加行之后,我也可以看到这些消息:
print task.__str__()
但我没有看到以下错误消息。此外,请注意,此循环不会退出,直到任务完成而没有异常:
try:
task.execute(self)
break
except engine.NetworkException:
print 'NETWORK PROBLEM DETECTED. Reconnecting.'
self.reconnect()
except:
print 'UNKNOWN EXCEPTION OCCURED. Reconnecting.'
self.reconnect()
def reconnect(self):
# [...]
ControlTask
在dispatch
上调用Gatherer
,然后将任务计算的数据写入数据库:
def dispatch(self, player):
self.db_cursor.execute('''INSERT INTO dispatched VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', (\
None, player.deadline, player.age, player.tsi, \
player.speciality, player.skills[0], player.skills[1], \
player.skills[2], player.skills[3] , player.skills[4], \
player.skills[5], player.skills[6], player.skills[7], \
player.skills[8], player.skills[9], player.skills[10]))
self.db.commit()
Gatherer
在实例化时创建数据库,并在垃圾回收时关闭数据库连接:
def __init__(self):
self.tasks = Queue.PriorityQueue()
self.db = sqlite3.connect('%s.db' % time.strftime('%d.%m.%Y %H:%M'))
self.db_cursor = self.db.cursor()
self.db_cursor.execute('''CREATE TABLE IF NOT EXISTS dispatched (
amount int, deadline int, age int, tsi int, speciality text,
s1 int, s2 int, s3 int, s4 int, s5 int, s6 int,
s7 int, s8 int, s9 int, s10 int, s11 int)''')
self.db_cursor.execute('''CREATE TABLE IF NOT EXISTS missed (
missed_from int, missed_until int,
min_age int, max_age int,
min_lvl int, max_lvl int)''')
def __del__(self):
self.db.close()
最后,这是实际的程序:
if __name__ == '__main__':
gt = Gatherer()
tasks_processed = 0
while True:
print 'Starting %d. task while %d are enqueued:' % \
(tasks_processed+1, gt.tasks.qsize())
try:
gt.process_next_task()
except KeyboardInterrupt:
break
except:
del gt
raise
tasks_processed = tasks_processed + 1