尽管守护程序设置为True,Python线程仍未停止

时间:2018-11-24 16:15:43

标签: python multithreading proxy urllib

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

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属性是否错误,还是应该设置其他参数以确保线程停止?

1 个答案:

答案 0 :(得分:0)

浏览了文档和其他一些资源之后,我发现线程确实关闭了,但是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()函数中。

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