使用subprocess.Popen结合线程实现ping设备功能返回错误结果求助
问题分析与修复方案
核心问题
你的代码在多线程环境下出错的根本原因是全局列表ping_cmd被多个线程共享并修改:
ping_cmd是全局变量,每次调用ping_ip(ip)都会执行ping_cmd.append(ip),当多个线程并行执行时,这个列表会不断追加IP地址,导致最终的ping命令格式完全错误(比如变成ping -c 4 -W 2 192.168.0.100 192.168.0.1 ...),根本无法正确执行ping操作。- 额外问题:使用集合
{ip, result}存储结果,这会导致键值对无序且格式混乱,应该用字典{ip: result}。
修复代码
修改ping.py
from utilities.env import PACKET_COUT, PING_TIME, MAX_WORKERS_COUNT from utilities.cmds import create_ping_cmd from subprocess import Popen, PIPE, DEVNULL, TimeoutExpired from re import findall from concurrent.futures import ThreadPoolExecutor MAX_PING_TIME = float(PACKET_COUT) * float(PING_TIME) def check_ping_process(ping_process): try: out = ping_process.communicate(timeout=MAX_PING_TIME)[0] # 检查是否有TTL字段(表示收到响应) has_ttl = bool(findall(r"TTL", out)) return ping_process.returncode == 0 and has_ttl except TimeoutExpired: ping_process.kill() return False def ping_ip(ip): # 每次调用都创建新的ping命令列表,避免全局变量共享冲突 ping_cmd = create_ping_cmd() ping_cmd.append(ip) ping_process = Popen( ping_cmd, stdout=PIPE, stderr=DEVNULL, text=True ) return check_ping_process(ping_process) def ping_ip_list(ip_list): ping_results = [] with ThreadPoolExecutor(max_workers=MAX_WORKERS_COUNT) as executor: results = executor.map(ping_ip, ip_list) for ip, result in zip(ip_list, results): result_dict = {ip: result} print(result_dict) ping_results.append(result_dict) return ping_results
可选优化main.py(让结果可返回/查看)
from ping import ping_ip_list ip_list = [ '192.168.0.100', '192.168.0.1', '192.168.0.104', '192.168.0.124', '192.168.0.103' ] def monitor_network_devices(ip_list): results = ping_ip_list(ip_list) return results # 调用并打印结果 if __name__ == "__main__": device_status = monitor_network_devices(ip_list) print("\n最终检测结果:") for status in device_status: print(status)
修复说明
- 移除全局
ping_cmd:在ping_ip函数内部每次创建新的命令列表,确保每个线程使用独立的ping命令,避免多线程间的变量干扰。 - 修正结果存储格式:用字典
{ip: result}替代集合,保证结果的键值对应关系清晰。 - 简化
check_ping_process逻辑:去掉无用的ping_result字典,直接返回布尔值,代码更简洁。
内容的提问来源于stack exchange,提问作者Makhsudjon
相关产品推荐
相关产品推荐

