Python 多处理和队列

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

在搜索了一些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

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