Skip to main content
 首页 » 编程设计

Python线程通信解决方案

2025年05月04日10artech

我正在编写一个用 Python 编写的非常基本的多线程网络爬虫,并为爬取页面和提取 url 的函数使用 While 循环,如下所示:

def crawl(): 
    while True: 
        try: 
            p = Page(pool.get(True, 10)) 
        except Queue.Empty: 
            continue 
 
        # then extract urls from a page and put new urls into the queue 

(完整源码在另一个问题中:Multi-threaded Python Web Crawler Got Stuck)

现在理想情况下,我想向 While 循环添加一个条件,使 while 循环在以下情况下退出:

  1. 池(存储 url 的队列对象)为空,并且;

  2. 所有线程都在阻塞,等待从队列中获取 url(这意味着没有线程将新 url 放入池中,因此让它们等待没有意义,并且会使我的程序卡住。)

例如,像这样的东西:

#thread-1.attr == 1 means the thread-1 is blocking. 0 means not blocking 
 
while not (pool.empty() and (thread-1.attr == 1 and thread-2.attr == 1 and ...)): 
    #do the crawl stuff 

所以我想知道线程是否可以检查其他事件线程正在做什么,或者其他事件线程的状态或属性值。

threading.Event()官方文档看了,还是想不通。

希望这里有人能给我指明方向:)

非常感谢!

马库斯

请您参考如下方法:

你可以尝试从头开始实现你想要的,现在我想到了不同的解决方案:

  • 使用threading.enumerate( ) 检查是否有线程仍然存在。
  • 尝试实现一个线程池,让您知道哪些线程仍处于事件状态,哪些返回到池中,这也有限制抓取第三方网站的线程数量的好处(例如检查 here) .

如果你不想重新发明轮子,你可以使用现有的实现线程池的库,或者你也可以检查使用绿色线程的 gevent 并提供 thread pool ,我已经使用类似的东西实现了类似的东西:

while 1: 
    try: 
        url = queue.get_nowait() 
    except Empty: 
        # Check that all threads are done. 
        if pool.free_count() == pool.size: 
            break 
    ... 

您还可以在队列中写入标记爬行结束的哨兵对象,并退出主循环并等待线程完成(例如使用池)。

while 1: 
    try: 
        url = queue.get_nowait() 
        # StopIteration mark that no url will be added to the queue anymore. 
        if url is StopIteration: 
             break 
    except Empty: 
        continue 
    ... 
pool.join() 

您可以选择自己喜欢的,希望这对您有所帮助。