为python多处理创建非常大的队列

时间:2019-04-09 03:16:31

标签: python multiprocessing

我想创建一个约256K的文件路径队列,并让这些路径由并行工作进程出队和处理。这是多处理而非线程。

但是,当我创建一个multiprocessing.queue时,队列中的32K对象似乎受到严格限制。如果对象是文件的完整路径,则可能会更小。

为多处理创建多服务器队列的替代方法是什么?

import multiprocessing
import sys

q = multiprocessing.Queue()

for i in range(32768 * 2):
    print i
    try:
        q.put('abcdef')
    except:
        print "Unexpected error on ()".format(i), sys.exc_info()[0]
        raise

产量:

...
32766
32767
Traceback (most recent call last):
Unexpected error on () <type 'exceptions.KeyboardInterrupt'>
  File "/Users/Wes/Dropbox/Programming/ElectionTransparency/vops_addons/dead/tryq.py", line 13, in <module>
    q.put('abc')
  File "/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/queues.py", line 101, in put
    if not self._sem.acquire(block, timeout):
KeyboardInterrupt

2 个答案:

答案 0 :(得分:0)

您可以尝试使用celery-http://www.celeryproject.org/-队列限制取决于代理配置。

此外,您将不仅限于同一台计算机上的工作程序-任何可以安装相同文件系统的计算机都可以运行celery worker处理您的任务。 (尽管如果不能进行远程处理,则使用芹菜工作者仍然比原始多处理具有优势,因为它具有诸如自动重试之类的优点)

答案 1 :(得分:0)

这是我终于发现有效的方法。我使路径数组可用于所有工作进程,并使用multiprocessing.Value()对象在由锁保护的数组中创建共享索引。

from multiprocessing import Process, Lock, Value
import os
import sys
import time

def info(title, lock, item=None):
    pid = os.getpid()
    lock.acquire()
    print '<', title, item,' ', __name__, pid, '>'
    sys.stdout.flush()
    lock.release()

def f(stdout_lock, next_item, worklist):
    while True:
        with next_item.get_lock():
            if len(worklist) <= next_item.value:
                return
            item = worklist[next_item.value]
            next_item.value += 1
        info('queue item: ', stdout_lock, item)
        time.sleep(0.0001)

if __name__ == '__main__':
    next_item = Value('l')
    worklist = [str(i) for i in range(250000)]
    next_item.value = 0
    stdout_lock = Lock()
    plist = []
    for i in range(3):
        plist.append(Process(target=f, args=(stdout_lock, next_item, worklist)))
        plist[-1].start()
    for i in range(3):
        plist[i].join()