Python 在真实条件下退出所有正在运行的线程

标签 python multithreading

我正在使用线程从 API url 检查 header 状态代码。如果条件为真,我如何打破循环/停止所有其他线程。请检查以下代码..

import logging, time, threading, requests

#: Log items
logging.basicConfig(format='%(asctime)s %(levelname)s : %(message)s', level=logging.INFO)

class EppThread(threading.Thread):
    def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None):
        threading.Thread.__init__(self, group=group, target=target, name=name, verbose=verbose)
        self.args = args

    def run(self):
        startTime = time.time()
        url = self.args[0]
        limit = self.args[1]

        for i in range(limit):
            response = requests.get(url)
            if response.status_code != 200:
                break
                #Exit other similar threads (with same url)
            else:
                print('Thread {0} - success'.format(thread.getName()))

         print('process completed')
         # Send Email


number_of_threads = 5
number_of_requests = 100

urls = ['https://v1.api.com/example', 'https://v2.api.com/example']

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

    for url in urls:
        threads = []
        for i in range(number_of_threads):
            et = EppThread(name = "{0}-Thread-{1}".format(name, i + 1), args=(url, number_of_requests))
            threads.append(et)
            et.start()

    # Check if execution time is not greater than 1 minute  
    while len(threads) > 0 and (time.time() - startTime) < 60:
        time.sleep(0.5)
        for thread in threads:
            if not thread.isAlive():
                threads.remove(thread)
                print('Thread {0} terminated'.format(thread.getName()))

    os._exit(1)

如果条件在任何正在运行的线程中为真,请提出一些停止代码执行的更好方法。

感谢您的帮助。

最佳答案

这里需要注意的一点是,当一个Threadrun方法执行完成后,这个Thread就会被置为dead和garbage集。所以我们真正需要的是一个 boolean 类变量来打破这个循环。类变量对于从该类和子类实例化的所有对象都是相同的;所以一旦我们设置了它,我们类中的所有对象都会以相同的方式运行:

import logging, time, threading, requests

#: Log items
logging.basicConfig(format='%(asctime)s %(levelname)s : %(message)s', level=logging.INFO)


class EppThread(threading.Thread):
    kill = False  # new Boolean class variable
    url = 'https://v1.api.com/example'  # keep this in mind for later

    def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None):
        threading.Thread.__init__(self, group=group, target=target, name=name, verbose=verbose)
        self.args = args

    def run(self):
        limit = self.args[0]

        for i in range(limit):
            response = requests.get(self.url)
            if response.status_code != 200:
                self.kill = True  # ends this loop on all Threads since it's changing a class variable

            else:
                print('Thread {0} - success'.format(self.getName()))  # changed to self.getName()

            if self.kill:  # if kill is True, break the loop, send the email, and finish the Thread
                break

        print('process completed')
        # Send Email


number_of_threads = 5
number_of_requests = 100

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

    threads = []
    for i in range(number_of_threads):
        et = EppThread(name="{0}-Thread-{1}".format(name, i + 1), args=(number_of_requests))
        threads.append(et)
        et.start()

    # Check if execution time is not greater than 1 minute
    while threads and time.time() - startTime < 60:  # removed len() due to implicit Falsiness of empty containers in Python
        time.sleep(0.5)
        for thread in threads:
            if not thread.isAlive():
                threads.remove(thread)
                print('Thread {0} terminated'.format(thread.getName()))

    EppThread.kill = True

现在,当任何 EppThreads 有一个错误的连接时,它会将类变量设置为 True,这使得所有其他 EppThread也打破循环。我还在末尾添加了 EppThread.kill = True,因此如果运行时间超过 1 分钟,它会更干净地中断请求循环。

最后,我添加了 url 类变量。这是因为您表示有兴趣同时运行不同的 url,并且只终止那些连接特别糟糕的 url。此时您所要做的就是继承 EppThread 并覆盖 killurl

class EppThread2(EppThread):
    kill = False
    url = 'https://v2.example.com/api?$awesome=True'

然后您可以实例化 EppThread2 并将其添加到 threads 列表中,一切都应该按您希望的方式运行。

关于Python 在真实条件下退出所有正在运行的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46226455/

相关文章:

java - 重写 SwingWorker 中的 process() 方法

c++ - MFC UI 线程中的进度条被阻止

python - 为 mac 制作 pygame/SDL 安装程序

C++ 11通过两种算法之一完成任务

python - Pandas 时间序列的线性回归

python - 如何在 dynamodb 中使用两个不同的凭据来拥有只读用户和所有访问用户?

ios - 对于 iOS,Concurrency Programming Guide 和 Threading Programming Guide 有什么区别?

java - 切入点可以动态地指定线程吗?

Python OpenCV 识别裁剪行

python - 在 Python 中乘以与 C++ 相同的精度