Python处理多线程的最佳方法是什么

Python处理多线程的最佳方法是什么,python,multithreading,Python,Multithreading,因为我的scape一次运行一个页面的速度太慢了,所以我尝试使用thread使它运行得更快。我有一个功能scrapewebsite,它接收一个网站来进行刮取,因此我可以轻松地创建每个线程并调用每个线程的start 现在我想实现一个num_threads变量,它是我想同时运行的线程数。处理这些多线程的最佳方法是什么 例如:假设num_threads=5,我的目标是启动5个线程,然后抓取列表中的前5个网站并将其删除,然后如果线程3完成,它将立即从列表中抓取第6个网站进行删除,而不是等到其他线程结束 有

因为我的scape一次运行一个页面的速度太慢了,所以我尝试使用thread使它运行得更快。我有一个功能scrapewebsite,它接收一个网站来进行刮取,因此我可以轻松地创建每个线程并调用每个线程的start

现在我想实现一个num_threads变量,它是我想同时运行的线程数。处理这些多线程的最佳方法是什么

例如:假设num_threads=5,我的目标是启动5个线程,然后抓取列表中的前5个网站并将其删除,然后如果线程3完成,它将立即从列表中抓取第6个网站进行删除,而不是等到其他线程结束

有没有关于如何处理的建议?谢谢

视情况而定

如果您的代码大部分时间都在等待网络操作,那么在web抓取应用程序中,线程是合适的。实现线程池的最佳方法是在3.4中使用concurrent.futures。如果做不到这一点,您可以创建一个threading.Queue对象,并将每个线程写入一个无限循环,该循环使用队列中的工作对象并对其进行处理

如果您的代码在下载数据后大部分时间都在处理数据,那么由于GIL,线程是无用的。concurrent.futures提供了对进程并发性的支持,但同样只适用于3.4+。对于较旧的python,请使用多处理。它提供了一种池类型,简化了创建进程池的过程


您应该使用cProfile分析您的代码,以确定您正在经历这两种情况中的哪一种。

如果您使用的是Python 3,请查看concurrent.futures.ThreadPoolExecutor

从文档中提取的示例:

如果您使用的是Python 2,则有一个可用的后端口:

:


也许这会有所帮助?但我不确定你真的需要穿线吗?只是某种队列?您考虑过使用吗。@trainoasis是的,它就像队列,5个线程将从该队列中提取数据以执行它们感谢,我将大部分时间花在程序上进行刮取,数据将保存到文本文件中,稍后将由另一个脚本使用。有一个可用的后端口,我编辑了答案以包含它
import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

# Retrieve a single page and report the url and contents
def load_url(url, timeout):
    conn = urllib.request.urlopen(url, timeout=timeout)
    return conn.readall()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))
from concurrent import futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

def load_url(url, timeout):
    return urllib.request.urlopen(url, timeout=timeout).read()

with futures.ThreadPoolExecutor(max_workers=5) as executor:
    future_to_url = dict((executor.submit(load_url, url, 60), url)
                         for url in URLS)

    for future in futures.as_completed(future_to_url):
        url = future_to_url[future]
        if future.exception() is not None:
            print('%r generated an exception: %s' % (url,
                                                     future.exception()))
        else:
            print('%r page is %d bytes' % (url, len(future.result())))