繁体   English   中英

杀死所有工作者/线程ThreadPoolExecutor

[英]Killing all workers/threads ThreadPoolExecutor

在过去的一天里,我一直在努力解决当前的问题。

我有一个python脚本,应该使用线程计数并根据每个线程执行请求。

每个线程都通过一个名为doit()的函数,该函数具有while True函数。 此循环仅在满足特定条件时才会中断,并且在中断时,以下线程也会中断。

我要实现的是,一旦这些线程/工作程序之一从其请求中获取状态代码200,所有工作程序/线程均应停止。 我的问题是即使满足条件,它也不会停止。

这是我的代码:

import threading
import requests
import sys
import urllib.parse
import concurrent.futures
import simplejson
from requests.auth import HTTPDigestAuth
from requests.packages import urllib3
from concurrent.futures import ThreadPoolExecutor

def doit(PINStart):
    PIN = PINStart
    while True:
        req1 = requests.post(url, data=json.dumps(data), headers=headers1, verify=False)
        if str(req1.status_code) == "200":
            print(str(PINs))
            c0 = req1.content
            j0 = simplejson.loads(c0)
            AuthUID = j0['UserId']
            print(UnAuthUID)
            AuthReqUser()
            #Kill all threads/workers if any of the threads get here.
            break
        elif(PIN > (PINStart + 99)):
              break
        else:
            PIN+=1

def main():
    threads = 100
    threads = int(threads)
    Calcu = 10000/threads
    NList = [0]
    for i in range(1,threads):
        ListAdd = i*Calcu
        if ListAdd == 10000:
            NList.append(int(ListAdd))
        else:
            NList.append(int(ListAdd)+1)

    with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor:
        tGen = {executor.submit(doit, PinS): PinS for PinS in NList}
        for NLister in concurrent.futures.as_completed(tGen):
            PinS = tGen[NLister]



if __name__ == "__main__":
    main()

我了解为什么会这样。 因为我只中断了其中一个线程的while True循环,所以其他99个线程(默认情况下,我使用100个线程运行代码)直到它们完成计数(循环运行100次或获取状态)时才中断代码200)。

我最初的工作是在代码顶部定义一个全局变量,然后在Counter <10000时进行了更改,这意味着它将对所有工作程序运行循环,直到Counter大于10000。并且在循环内它将递增全局变量。 。 这样,当一个工作人员获得状态码200时,我将Counter(我的全局变量)设置为例如15000(大于10000),因此所有其他工作人员都停止运行该循环100次。

这没有用。 当我将其添加到代码中时,所有线程都会立即停止,甚至一次都不会循环运行。

这是此解决方案的示例代码:

import threading
import requests
import sys
import urllib.parse
import concurrent.futures
import simplejson
from requests.auth import HTTPDigestAuth
from requests.packages import urllib3
from concurrent.futures import ThreadPoolExecutor
global Counter
def doit(PINStart):
    PIN = PINStart
    while Counter < 10000:
        req1 = requests.post(url, data=json.dumps(data), headers=headers1, verify=False)
        if str(req1.status_code) == "200":
            print(str(PINs))
            c0 = req1.content
            j0 = simplejson.loads(c0)
            AuthUID = j0['UserId']
            print(UnAuthUID)
            AuthReqUser()
            #Kill all threads/workers if any of the threads get here.
            Counter = 15000
            break
        elif(PIN > (PINStart + 99)):
            Counter = Counter+1
            break
        else:
            Counter = Counter+1
            PIN+=1

def main():
    threads = 100
    threads = int(threads)
    Calcu = 10000/threads
    NList = [0]
    for i in range(1,threads):
        ListAdd = i*Calcu
        if ListAdd == 10000:
            NList.append(int(ListAdd))
        else:
            NList.append(int(ListAdd)+1)

    with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor:
        tGen = {executor.submit(doit, PinS): PinS for PinS in NList}
        for NLister in concurrent.futures.as_completed(tGen):
            PinS = tGen[NLister]



if __name__ == "__main__":
    main()

关于从发出的一个请求中获取状态码200后如何杀死所有工作人员的任何想法?

问题是您没有使用全局变量。

要在函数中使用全局变量,必须将global语句放在该函数中 ,而不是放在顶层。 因为没有,所以doit内部的Counter是一个局部变量。 您分配给函数中任何位置的任何变量都是本地变量,除非您具有global (或非nonlocal )声明。

在您为其分配任何内容之前,第一次使用该本地Counter就在while循环的顶部。 因此,它将立即引发UnboundLocalError

此异常将作为将来的结果传播回主线程​​。 您会看到的,只是您从未真正评估过期货。 您只需执行以下操作:

   tGen = {executor.submit(doit, PinS): PinS for PinS in NList}
   for NLister in concurrent.futures.as_completed(tGen):
        PinS = tGen[NLister]

因此,您将获得与您运行的功能相对应的PinS ,但无需查看结果或异常。 你只是忽略它。 因此,您看不到要重新获得100个例外,任何例外都可以告诉您实际出了什么问题。 这等效于裸露的except: pass非线程代码。 即使您出于某种原因不希望检查“生产”中的期货结果,也绝对应该在调试问题时进行检查。

无论如何,只要将global变量放置在正确的位置即可,您的错误已修复。


但是,您确实至少还有另外两个问题。

首先,在线程之间共享全局而不同步它们是不安全的。 在CPython中,由于有了GIL,您永远不会因为它而遭受段错误,并且您经常完全摆脱它,但往往却没有。 您可能会错过计数,因为两个线程试图同时执行Counter = Counter + 1 ,因此它们都将其从42递增到43。并且您可以while Counter < 10000:获得陈旧的值while Counter < 10000:检查并遍历循环额外的时间。

其次,在完成下载和处理完整的请求之前,不要检查Counter 根据您的超时设置,这可能需要几秒钟,甚至几分钟。 并添加一个事实,您可能会在知道要退出的时候再经历一次循环……

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM