ThreadPoolExecturor 未来永远不会完成

ThreadPoolExecturor future never finishing

我正在为一个程序编写后端,该程序需要能够 ping 网络上的所有设备以查看它们是否存在。这个后端运行在烧瓶套接字上。我写了一个简单的测试脚本,它使用 threadExecutor 和 futures 来加速这个过程。

import platform
import subprocess
import netifaces as ni
import concurrent.futures
import socket

baseIP = ni.ifaddresses('enp4s0')[ni.AF_INET][0]['addr']
prefix = '.'.join(baseIP.split('.')[0:3])
aliveIPs = []

def ping(ip):
    command = ['ping', '-c 1', '-w 5', ip]
    print(ip)
    if(subprocess.call(command) == 0):
        return socket.gethostbyaddr(ip)
    else:
        return ''

ips = [prefix + '.' +str(i) for i in range(0,255)]

with concurrent.futures.ThreadPoolExecutor() as executor:
    futures = []
    for ip in ips:
        futures.append(executor.submit(ping, ip=ip))
    for future in concurrent.futures.as_completed(futures):
        res = future.result()
        if(res != ''):
            aliveIPs.append(res)

print(aliveIPs)

这段代码在我的电脑上 运行 和 python3 工作正常,并为我提供了网络上的设备列表。

但是当我将此代码实施到我的烧瓶应用程序中时,未来永远不会完成,导致它挂在它尝试扫描的第一个 ip 上。以下代码来自我的烧瓶应用程序。

def ping(ip):
    print(ip)
    proc = subprocess.run(['ping', '-c 1', '-w 5', ip])
    if(proc == 0):
        print("alive")
        return socket.gethostbyaddr(ip)
    else:
        print("none")
        return ''


"""
gets a list of available hosts in the network for a connection
"""


def update_worker_list(executor):
    print("updating")
    network_device = get_network_info()['net_name']
    ip = ni.ifaddresses(network_device)[ni.AF_INET][0]['addr']
    ipPrefix = '.'.join(ip.split('.')[0:3])
    alive_ips = []

    ips = [ipPrefix + '.' + str(i) for i in range(0, 255)]
    futures = []
    for ip in ips:
        futures.append(executor.submit(ping, ip=ip))
    for future in concurrent.futures.as_completed(futures):
        res = future.result()
        if(res != ''):
            alive_ips.append(res)
    print(alive_ips)

这里的executor参数是flask-executor pip包中的一个flask_executor。它是这样激发的:

app = Flask(__name__)
app.config['SECRET_KEY'] = DEV_SECRET
app.config['DEBUG'] = True
app.config['EXECUTOR_TYPE'] = 'thread'
app.config['EXECUTOR_MAX_WORKERS'] = 20
executor = Executor(app)

我最初尝试使用 python 提供的执行程序,但这导致了同样的错误。 以下是 update_workers_list 函数对 STDOUT 的输出:

updating
192.168.8.0
Do you want to ping broadcast? Then -b. If not, check your local firewall rules.
none

我正在寻找关于为什么未来没有解决的任何想法。

所以在挖掘 flask-socketIO 的源代码后,我发现 socketIO 喜欢占用线程。这意味着您必须使用 gevent 或 eventlet 自行修补它以使用另一个。 post 解释得很好,并引导我修复我的错误。