首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python处理多线程的最佳方法是什么

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

Stack Overflow用户
提问于 2015-02-04 04:38:58
回答 2查看 1.1K关注 0票数 0

因为我的scaper运行很慢(一次一个页面),所以我试着使用线程来让它工作得更快。我有一个抓取(网站)函数,它接受一个要抓取的网站,所以我可以很容易地创建每个线程并在每个线程上调用start()。

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

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

有什么关于如何处理它的建议吗?谢谢

EN

回答 2

Stack Overflow用户

发布于 2015-02-04 04:46:20

那得看情况。

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

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

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

票数 0
EN

Stack Overflow用户

发布于 2015-02-04 04:48:09

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

从文档ThreadPoolExecutor Example中提取的示例

代码语言:javascript
运行
复制
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)))

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

ThreadPoolExecutor Example

代码语言:javascript
运行
复制
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())))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28308285

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档