multiprocess:识别队列中的进程

时间:2013-01-12 08:53:16

标签: python python-3.x multiprocessing

我有一个多进程程序,可以获取所有响应时间不同的网页。结果根据FIFO规则存储在进程队列中。我想通过进程号识别队列中的结果。这是我的测试装备和我到目前为止使用两个队列所取得的成就。还有其他方法吗?我试图使用全局列表来存储结果,但这两个进程似乎没有共享相同的内存空间。

#!/usr/bin/python3.2

import time
from multiprocessing import Process, Queue

def myWait(processNb, wait, resultQueues):
    startedAt = time.strftime("%H:%M:%S", time.localtime())
    time.sleep(wait)
    endedAt = time.strftime("%H:%M:%S", time.localtime())
    resultQueues[processNb].put('Process %s started at %s wait %s ended at %s' % (processNb, startedAt, wait, endedAt))

# queue initialisation
resultQueues = [Queue(), Queue()]

# process creation arg: (process number, sleep time, queue)
proc =  [
    Process(target=myWait, args=(0, 2, resultQueues,)),
    Process(target=myWait, args=(1, 1, resultQueues,))
    ]

# starting processes
for p in proc:
    p.start()

for p in proc:
    p.join()

# print results
print(resultQueues[0].get())
print(resultQueues[1].get())

2 个答案:

答案 0 :(得分:2)

不,当您使用multiprocessing时,进程将不会共享地址空间 - 它与所有进程共享内存的threading不同。这意味着您希望在进程之间共享的任何内容都必须通过进程之间的显式连接,例如Queue

如果你想要的是组合所有进程的结果,你实际上可以只使用一个结果队列 - 它们可以安全地被多个进程(和多个线程)一次访问。然后,您的所有工作人员都可以将结果插入到该队列中,主进程可以在它们进入时读取它们。

以上是您修改​​的代码,使用单个队列:

#!/usr/bin/python3.2

import time
from multiprocessing import Process, Queue

def myWait(processNb, wait, results):
    startedAt = time.strftime("%H:%M:%S", time.localtime())
    time.sleep(wait)
    endedAt = time.strftime("%H:%M:%S", time.localtime())
    results.put('Process %s started at %s wait %s ended at %s' % (processNb, startedAt, wait, endedAt))

# queue initialisation
results = Queue()

# process creation arg: (process number, sleep time, queue)
proc =  [
    Process(target=myWait, args=(0, 2, results,)),
    Process(target=myWait, args=(1, 1, results,))
    ]

# starting processes
for p in proc:
    p.start()

for p in proc:
    p.join()

# print results
print(results.get())
print(results.get())

如果您想要识别每个结果的过程而不必阅读字符串,您可以轻松地将其添加为2元组。这将改变代码如下(我只显示了更改的部分):

import time
import multiprocessing
import queue

def myWait(processNb, wait, results):
    startedAt = time.strftime("%H:%M:%S", time.localtime())
    time.sleep(wait)
    endedAt = time.strftime("%H:%M:%S", time.localtime())
    results.put((processNb, 'Process %s started at %s wait %s ended at %s' % (processNb, startedAt, wait, endedAt)))

# queue initialisation
results = multiprocessing.Queue()

# process creation arg: (process number, sleep time, queue)
proc =  [
    multiprocessing.Process(target=myWait, args=(0, 2, results,)),
    multiprocessing.Process(target=myWait, args=(1, 1, results,))
    ]

# starting processes
for p in proc:
    p.start()

for p in proc:
    p.join()

# print results
while True:
    try:
        processNb, message = queue.get_nowait()
        print "Process %d sent: %s" % (processNb, message)
    except queue.Empty:
        break

这有帮助吗?

编辑:正如另一个响应者非常正确地指出的那样,传递比字符串更多的结构化数据可能更好,但我试图让我的例子与你的相似,以用于解释目的。事实上,为了使未来的更改变得更容易,我会使用你可以按名称而不是元组索引的东西(所以你不必仅限于添加项目到最后)。

您可以使用自己的类,也可以只使用collections.namedtuple来完成工作(如果您希望以后扩展已使用元组代替名称的代码,后者特别有用,允许逐步迁移)。

请记住(据我所知)你可以在队列中传递pickled的任何内容。

答案 1 :(得分:1)

  • mp.Process可以为目标提供name参数 然后,函数myWait可以使用mp.current_process().name进行访问。 因此没有必要通过processNb
  • 将进程间通信保持在最低限度。而不是通过 通过队列格式化字符串,只需传递字符串的部分 这将在元组中发生变化:(name, wait, startedAt, endedAt)

所以,你可以用这样一个队列来做:

import time
import multiprocessing as mp

def myWait(wait, resultQueue):
    startedAt = time.strftime("%H:%M:%S", time.localtime())
    time.sleep(wait)
    endedAt = time.strftime("%H:%M:%S", time.localtime())
    name = mp.current_process().name
    resultQueue.put(
        (name, wait, startedAt, endedAt))


# queue initialisation
resultQueue = mp.Queue()

# process creation arg: (process number, sleep time, queue)
proc =  [
    mp.Process(target=myWait, name = '0', args=(2, resultQueue,)),
    mp.Process(target=myWait, name = '1', args=(1, resultQueue,))
    ]

# starting processes
for p in proc:
    p.start()

for p in proc:
    p.join()

# print results
for p in proc:
    name, wait, startedAt, endedAt = resultQueue.get()
    print('Process %s started at %s wait %s ended at %s' %
          (name, startedAt, wait, endedAt))