首页 > 解决方案 > 尽管守护进程设置为 True,但 Python 线程并没有停止

问题描述

我认为这是一个显而易见的问题,但我正在制作一个使用线程来测试代理的脚本,并且一旦找到一定数量的代理就应该停止。当我运行它时,如果满足条件,线程将停止生成输出,但程序不会关闭。我看过其他类似的问题,但似乎无法成功实施。将不胜感激任何指针。

import queue
import threading

import time   
import urllib.request

class ThreadUrl(threading.Thread):

    def __init__(self, queue, working_proxies):
        threading.Thread.__init__(self)
        self.queue = queue
        self.working_proxies = working_proxies

    def run(self):
        while len(self.working_proxies)<5:

            proxy = self.queue.get()

            try:
                proxy_handler = urllib.request.ProxyHandler({'http': proxy})
                opener = urllib.request.build_opener(proxy_handler)
                opener.addheaders = [('User-agent',
                                      'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36')]
                urllib.request.install_opener(opener)
                req = urllib.request.Request('http://www.wikipedia.org')
                sock=urllib.request.urlopen(req)
                print(f'{proxy} works')
                with appending_lock:
                    self.working_proxies.append(proxy)

            except urllib.request.HTTPError as e:
                print('Error code: ', e.code)

            except Exception as detail:
                print("ERROR:", detail)

            self.queue.task_done()


def main(proxies, working_proxies):
    for i in range(5):
        t = ThreadUrl(queue,working_proxies)
        t.daemon = True
        t.start()


        for proxy in proxies:
            queue.put(proxy)

    queue.join()


if __name__ == '__main__':
    start = time.time()

    appending_lock = threading.Lock()
    proxies = [...list of proxies...]
    working_proxies = []

    queue = queue.Queue()

    main(proxies, working_proxies)
    print("Elapsed Time: %s" % (time.time() - start))

我是否使用了 daemon 属性错误,或者是否应该设置其他参数以确保线程停止?

标签: pythonmultithreadingproxyurllib

解决方案


在浏览了文档和其他一些资源之后,我发现线程确实关闭了,但是 queue.join() 函数一直阻塞,直到队列被清空。由于如果线程在完成队列中的所有项目之前被终止,则不会发生这种情况,因此脚本继续运行。

所以,我已经覆盖了 queue.join() 看起来像这样:

queue = queue.Queue()

def waiter(queue):
    while not queue.empty() and dead == False:
        pass

queue.join = waiter

如果确定满足关闭条件,则在线程内访问“死”变量。在上面的代码中,将在 run() 函数的 while 循环中放置 'dead' 而不是 'len(self.working_proxies)<5'。每次将新项目附加到 self.working_proxies 时,脚本应检查是否满足终止条件,如果满足,则将 'dead' 设置为 True。

此外,'dead' 是一个全局变量,因此不需要将其传递给新的 waiter() 函数。

我敢肯定有一种更优雅的方法来解决这个问题,但同时这个方法应该可以解决问题。


推荐阅读