我有一个带有queue
表的数据库,新的条目会连续插入队列中。
我希望Python脚本尽可能快地执行队列,我想我需要一些线程代码才能这样做,像守护进程一样运行。
但我无法弄清楚如何将数据库用作队列。
我正在看这个例子:
import MySQLdb
from Queue import Queue
from threading import Thread
def do_stuff(q):
while True:
print q.get()
q.task_done()
q = Queue(maxsize=0)
num_threads = 10
for i in range(num_threads):
worker = Thread(target=do_stuff, args=(q,))
worker.setDaemon(True)
worker.start()
// TODO: Use the DB
db = MySQLdb.connect(...)
cursor = db.cursor()
q = cursor.execute("SELECT * FROM queue")
for x in range(100):
q.put(x)
q.join()
答案 0 :(得分:3)
2个快点:
假设您正在使用cPython,GIL将有效 渲染线程无用,只允许1个线程通过 一次翻译。几个解决方法是:
Gevent
库[source]
gevent是一个基于协程的Python网络库,它使用 greenlet在libev之上提供高级同步API 事件循环。
multiprocessing
模块,可以生成多个进程 - 这是python中的真正并发。
concurrent.futures
模块 - python 3中的新模块,可用于端口
python 2. [source]
这是一个新的高级库,只能在“工作”级别运行,这意味着您不再需要大惊小怪 同步,或管理线程或进程。你只需指定一个 线程或进程池与一定数量的“工人”,提交
工作,并整理结果。它是Python 3.2中的新功能,但却是一个端口 Python 2.6+可在http://code.google.com/p/pythonfutures处获得。
您可以使用MySQLdb的SSDictCursor()
并执行fetchone()。这是一个流式游标,您可以在无限的while()循环中运行它以类似于队列:
cur = MySQLdb.cursors.SSDictCursor() cur.execute(query) while True: row = cursor.fetchone() if not row : break # (or sleep()!) else: # other
celery
或mongodb
这样的工具来模拟队列和工作人员。关系数据库不仅仅是针对那种工作而被削减,并且遭受不必要的碎片化。 Here's如果你想了解更多关于mysql中的碎片的话,那就是一个很好的来源。答案 1 :(得分:1)
我不确定它是否是最佳解决方案,但我想到了一个主线程的结构,它读取数据并填充队列。一定要避免双重。也许通过使用增加数字的主键很容易检查。
工作者结构很好,但是在评论中提到:GIL会避免任何提升。但是如果你的“do_stuff”独立于脚本本身就可以使用多处理(例如,任务是图片,“do_stuff”是“旋转图片90°”)。 Afaik它没有受到GIL的影响
https://docs.python.org/2/library/subprocess.html可以获得一些关于此的信息。
PS:英语不是我的母语。