Python 多处理和队列
在搜索了一些google和stackoverflow以及其他网站的帖子之后,我仍然对如何在代码上应用队列和线程感到困惑:Python 多处理和队列,python,python-multithreading,Python,Python Multithreading,在搜索了一些google和stackoverflow以及其他网站的帖子之后,我仍然对如何在代码上应用队列和线程感到困惑: import psycopg2 import sys import re # for threading and queue import multiprocessing from multiprocessing import Queue # for threading and queue import time from datetime import datetime
import psycopg2
import sys
import re
# for threading and queue
import multiprocessing
from multiprocessing import Queue
# for threading and queue
import time
from datetime import datetime
class Database_connection():
def db_call(self,query,dbHost,dbName,dbUser,dbPass):
try:
con = None
con = psycopg2.connect(host=dbHost,database=dbName,
user=dbUser,password=dbPass)
cur = con.cursor()
cur.execute(query)
data = cur.fetchall()
resultList = []
for data_out in data:
resultList.append(data_out)
return resultList
except psycopg2.DatabaseError, e:
print 'Error %s' % e
sys.exit(1)
finally:
if con:
con.close()
w = Database_connection()
sql = "select stars from galaxy"
startTime = datetime.now()
for result in w.db_call(sql, "x", "x", "x", "x"):
print result[0]
print "Runtime: " + str(datetime.now()-startTime)
假设结果为100+个值。如何将这100多个结果放入队列,然后使用队列和多处理模块执行(例如打印),然后每次执行5个结果?您希望这段代码做什么 由于
get()
返回队列()中的下一项,因此此代码没有输出。您正在将sql响应中的字母一次放入一个字母的队列中。i.的i
正在w.db\u call
返回的列表上循环。这些项目是(我假设)字符串,然后您将对其进行迭代,并一次向队列添加一个。接下来要做的事情是从队列中删除刚才添加到队列中的元素,这会使队列在每次循环中保持不变。如果在循环中放入print
语句,它将打印出刚从队列中得到的字母
队列
用于在进程之间传递信息。我认为您正在尝试建立一个生产者/消费者模式,其中您有一个进程向队列添加内容,还有多个其他进程从队列中消费内容。请参阅(,)中包含的内容和链接
只要不需要在交互式shell中运行,可能最简单的方法就是使用Pool
(几乎一字不差地从
它将您想要执行的操作应用于每个结果(写入函数f
),并将该操作的结果作为列表返回。要使用的子进程数由参数设置为池我能够通过以下方法解决问题:
def worker():
w = Database_connection()
sql = "select stars from galaxy"
for result in w.db_call(sql, "x", "x", "x", "x"):
if result:
jobs = []
startTime = datetime.now()
for i in range(1):
p = multiprocessing.Process(target=worker)
jobs.append(p)
p.start()
print "Runtime: " + str(datetime.now()-startTime)
我相信这不是最好的方法,但现在解决了我的问题:)这是我的建议
import Queue
from threading import Thread
class Database_connection:
def db_call(self,query,dbHost,dbName,dbUser,dbPass):
# your code here
return
# in this example each thread will execute this function
def processFtpAddrMt(queue):
# loop will continue until queue containing FTP addresses is empty
while True:
# get an ftp address, a exception will be called when the
# queue is empty and the loop will break
try: ftp_addr = queue.get()
except: break
# put code to process the ftp address here
# let queue know this task is done
queue.task_done()
w = Database_connection()
sql = "select stars from galaxy"
ftp_addresses = w.db_call(sql, "x", "x", "x", "x")
# put each result of the SQL call in a Queue class
ftp_addr_queue = Queue.Queue()
for addr in ftp_addresses:
ftp_addr_queue.put(addr)
# create five threads where each one will run analyzeFtpResult
# pass the queue to the analyzeFtpResult function
for x in range(0,5):
t = Thread(target=processFtpAddrMt,args=(ftp_addr_queue,))
t.setDaemon(True)
t.start()
# blocks further execution of the script until all queue items have been processed
ftp_addr_queue.join()
它使用Queue类存储SQL结果,然后使用Thread类处理队列。创建了五个线程类,每个线程类使用processFtpAddrMt函数,该函数从队列中获取ftp地址,直到队列为空。您所要做的就是添加处理ftp地址的代码。希望这能有所帮助。我不确定这个结构是否是书面的,但似乎不是,我会阅读你的建议并适当地更新这个问题。谢谢。我用了一个更简单的例子来回答这个问题。为了避免混淆,您的问题是否与DB有关,也许您可以简化示例嗨,是的,它有,因为我需要对结果进行循环。@AnuragUniyal我刚刚用您的建议编辑了最后几行。这不是DB问题,对吗?因此,您应该更改那些psycopg2调用,将其替换为函数调用(可能是睡眠),以便至少有人可以按原样运行代码。因此,您希望在5个不同的线程中分析SQL响应的结果吗?这仍然只启动一个进程来完成所有工作。为什么范围(1)中的i的
?如果你想并行化,那么使用多处理.cpu\u count
(以及最终的其他数据)来使用“大量”的进程。我对python不太了解,这是我发现的在sql结果上只迭代一次的方法。你给你什么建议来代替它它跑了吗?看起来每次通过都应该启动一个新的进程,给你无限的递归。@tcaswell,不知道为什么它被否决了。事实上,它工作得很好(我现在正在使用它)。也许这不是最聪明的解决方案,但它用我有限的Python/开发知识解决了我的问题。
import Queue
from threading import Thread
class Database_connection:
def db_call(self,query,dbHost,dbName,dbUser,dbPass):
# your code here
return
# in this example each thread will execute this function
def processFtpAddrMt(queue):
# loop will continue until queue containing FTP addresses is empty
while True:
# get an ftp address, a exception will be called when the
# queue is empty and the loop will break
try: ftp_addr = queue.get()
except: break
# put code to process the ftp address here
# let queue know this task is done
queue.task_done()
w = Database_connection()
sql = "select stars from galaxy"
ftp_addresses = w.db_call(sql, "x", "x", "x", "x")
# put each result of the SQL call in a Queue class
ftp_addr_queue = Queue.Queue()
for addr in ftp_addresses:
ftp_addr_queue.put(addr)
# create five threads where each one will run analyzeFtpResult
# pass the queue to the analyzeFtpResult function
for x in range(0,5):
t = Thread(target=processFtpAddrMt,args=(ftp_addr_queue,))
t.setDaemon(True)
t.start()
# blocks further execution of the script until all queue items have been processed
ftp_addr_queue.join()