为什么我的多进程Python脚本永远不会结束?

时间:2015-03-02 10:05:29

标签: python python-3.x multiprocessing

我尝试了一些多进程示例,主要是:http://toastdriven.com/blog/2008/nov/11/brief-introduction-multiprocessing/我使用了简单的应用程序',它使用多进程来测试URL。 当我使用它(在Python 3.3中,在PyCharm IDE中的Windows上)进行一些修改,有很多URL时,我的脚本永远不会停止,我不明白为什么。

import httplib2
import sys
from multiprocessing import Lock, Process, Queue, current_process

def worker(work_queue, done_queue):
    for url in iter(work_queue.get, 'STOP'):
        try:
            print("In : %s - %s." % (current_process().name, url))
            status_code = print_site_status(url)
            done_queue.put("%s - %s got %s." % (current_process().name, url, status_code))
        except:
            done_queue.put("%s failed on %s with: %s" % (current_process().name, url, str(sys.exc_info()[0])))
    print("Out : %s " % (current_process().name))
    return True

def print_site_status(url):
    http = httplib2.Http(timeout=10)
    headers, content = http.request(url)
    return headers.get('status', 'no response')

def main():
    workers = 8
    work_queue = Queue()
    done_queue = Queue()
    processes = []
    with open("Annu.txt") as f: # file with URLs
        lines = f.read().splitlines()
    for surl in lines:
        work_queue.put(surl)

    for w in range(workers):
        p = Process(target=worker, args=(work_queue, done_queue))
        p.start()
        processes.append(p)
        work_queue.put('STOP')

    for p in processes:
        p.join()
    print("END")
    done_queue.put('STOP')

    for status in iter(done_queue.get, 'STOP'):
        print(status)

if __name__ == '__main__':
    main()

我看到所有网址状态都已经过测试,所有流程都是' Out'表示该过程结束的消息,但从来没有我的结束'信息。 我使用的网址列表是:http://www.pastebin.ca/2946850

那么......我的错误在哪里?是否与Python multiprocessing threads never join when given large amounts of work

重复

一些信息:当我压制' done_queue'代码中的任何地方:它的作品。

2 个答案:

答案 0 :(得分:0)

来自Queue documentation

  

如果可选的args块为true且timeout为None(默认值),则在必要时阻止,直到某个项可用为止。

这意味着你的循环永远不会终止。

您需要向get添加超时并在获得Empty异常时停止循环,或者在收到STOP消息时需要退出循环。< / p>

答案 1 :(得分:0)

好的,我找到了答案(在Python文档中:https://docs.python.org/3.4/library/multiprocessing.html#multiprocessing-programming):

  

警告如上所述,如果子进程已将项目放在a上   然后,队列(并且它没有使用JoinableQueue.cancel_join_thread)   在所有缓冲项都存在之前,该进程不会终止   冲到管道上。

所以改变代码:

    print("Out : %s " % (current_process().name))
    return True

通过:

    print("Out : %s " % (current_process().name))
    done_queue.cancel_join_thread()
    return True

我不明白为什么初始代码适用于少量网址...