【问题标题】:using multiple threads in Python在 Python 中使用多个线程
【发布时间】:2012-07-24 19:55:02
【问题描述】:

我正在尝试解决一个问题,我有很多(大约一万个)URL,并且需要从所有这些 URL 中下载内容。到目前为止,我一直在“链接中的链接:”循环中执行此操作,但是现在花费的时间太长了。我认为是时候实现多线程或多处理方法了。我的问题是,最好的方法是什么?

我知道全局解释器锁,但由于我的问题是网络限制的,而不是 CPU 限制的,我认为这不会是一个问题。我需要将数据从每个线程/进程传回主线程/进程。我不需要帮助实施任何方法(Terminate multiple threads when any thread completes a task 涵盖该方法),我需要关于采用哪种方法的建议。我目前的做法:

data_list = get_data(...)
output = []
for datum in data:
    output.append(get_URL_data(datum))
return output

没有其他共享状态。

我认为最好的方法是创建一个包含所有数据的队列,并让多个工作线程从输入队列中弹出,获取 URL 数据,然后推送到输出队列。

我说的对吗?有什么我想念的吗?这是我第一次用任何语言实现多线程代码,我知道这通常是一个难题。

【问题讨论】:

    标签: python multithreading


    【解决方案1】:

    对于您的具体任务,我建议您使用multiprocessing worker pool。您只需定义一个池并告诉它您想要使用多少个进程(默认情况下每个处理器内核一个)以及您想要在每个工作单元上运行的功能。然后,您准备好列表中的每个工作单元(在您的情况下,这将是一个 URL 列表)并将其提供给工作池。

    您的输出将是原始数组中每个工作项的工作函数的返回值列表。所有很酷的多处理优点都将在后台发生。当然还有其他使用工作池的方法,但这是我最喜欢的一种。

    多处理愉快!

    【讨论】:

    • +1。这绝对是最简单的解决方案。如果出于某种原因,您希望改用多线程解决方案,则实现非常简单。请参阅 codereview.stackexchange.com 上的 my implementation
    • 我以为多处理模块已经提供了一个(半隐藏的)ThreadPool 类:stackoverflow.com/questions/3033952/…
    【解决方案2】:

    像这样执行 IO 绑定任务的最快和最有效的方法是异步事件循环。 libcurl 可以做到这一点,并且有一个名为 pycurl 的 Python 包装器。使用它的“多”接口,您可以进行高性能的客户端活动。我已经完成了超过 1000 次的同时获取,其速度与一次一样快。

    但是,API 非常低级且难以使用。有一个简化的包装器here,您可以将其用作示例。

    【讨论】:

      【解决方案3】:

      在您的用例中,我能想到的最佳方法是使用线程池并维护工作队列。线程池中的线程从工作队列中获取工作,完成工作,然后去获得更多的工作。通过这种方式,您可以精细控制处理 URL 的线程数。

      因此,创建一个 WorkQueue,在您的情况下,它基本上是一个包含需要下载的 URL 的列表。

      创建一个线程池,它创建您指定数量的线程,从 WorkQueue 获取工作并将其分配给一个线程。每次线程完成并返回时,您都会检查工作队列是否有更多工作,并相应地再次将工作分配给该线程。您可能还想放置一个挂钩,以便每次将工作添加到工作队列时,如果可用,您的线程会将其分配给空闲线程。

      【讨论】:

        猜你喜欢
        • 2015-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-14
        • 1970-01-01
        相关资源
        最近更新 更多