Python - 多处理线程在使用Queue时不会关闭

时间:2015-07-01 20:13:49

标签: python multithreading python-3.x queue python-multiprocessing

这适用于Python 3.x

我以300块的形式从CSV文件加载记录,然后生成工作线程以将它们提交到REST API。我将HTTP响应保存在队列中,这样我就可以在处理完整个CSV文件后获得跳过记录数的计数。然而,在我向我的工作人员添加了一个队列后,线程似乎不再关闭了。我想监视线程的数量有两个原因:(1)一旦完成,我可以计算并显示跳过计数和(2)我想增强我的脚本产生不超过20个左右的线程,所以我不要用完记忆。

我有两个问题:

  • 有人可以解释为什么线程在使用#include <iostream> using namespace std; int n=0; int x=0; int s=0; int i=1; int main() { cin >> n; for(i=1; i<=n; i++) { cin >> x; int nr=1; while(x>9) { nr=nr*10; x=x/10; } s=s+x*nr; } cout << s; return 0; }
  • 时保持活动状态
  • 是否有不同的方法来管理线程数,并监控是否所有线程都已完成?

以下是我的代码(有些简化,因为我无法分享我正在呼叫的API的确切详细信息):

q.put()

1 个答案:

答案 0 :(得分:3)

这很可能是因为记录了multiprocessing.Queue

的怪癖
  

请记住,将项目放入队列的进程将等待   在终止之前,直到所有缓冲的项目都由   “馈线”螺纹到底层管道。 (子进程可以调用   队列的cancel_join_thread()方法以避免此行为。)

     

这意味着无论何时使用队列,您都需要确保这一点   所有已放入队列的项目最终都将被删除   在流程加入之前。否则你不能确定   将项目放入队列的进程将终止。请记住   此外,非守护进程将自动加入。

基本上,您需要确保get()来自Queue的所有项目,以确保putQueue内容的所有流程都能够退出。

我认为在这种情况下,您最好使用multiprocessing.Pool,并将所有工作提交至multiprocessing.Pool.map。这大大简化了事情,并使您可以完全控制正在运行的进程数:

def worker(leads):
    payload = {"action":"createOrUpdate","input":leads}
    r = requests.post(url, params=params, data=json.dumps(payload), headers=headers)
    return r.text

if __name__ == "__main__":
    pool = multiprocessing.Pool(multiprocessing.cpu_count() * 2)  # cpu_count() * 2 processes running in the pool
    responses = pool.map(worker, read_test_data(TEST_FILE))

    skipped_count = 0
    for raw_response in responses:
        http_response = json.loads(raw_response)
        for i in http_response['result']:
            if (i['status'] == "skipped" and i['reasons'][0]['code'] == "1004"):
                skipped_count += 1
    print("Number of records skipped: " + str(skipped_count))

如果您担心将read_test_data(TEST_FILE)转换为列表(使用Pool.map时需要)的内存成本,则可以使用Pool.imap代替。

修改

正如我在上面的评论中提到的,这个用例看起来像是I / O绑定,这意味着你可以通过使用multiprocessing.dummy.Pool(它使用线程池而不是进程池)看到更好的性能)。试一试,看看哪个更快。