我正在使用带有线程的 subprocess.Popen 类,但它对我不起作用

问题描述 投票:0回答:1

我有以下文件:

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))
ping_cmd = create_ping_cmd()

def check_ping_process(ping_process):
    ping_result = {}
    try:
        out = ping_process.communicate(timeout=MAX_PING_TIME)[0]
        is_successes = findall("TTL", out)
        if ping_process.returncode == 0 and is_successes:
            return True
        else:
            return False
    except TimeoutExpired:
        ping_process.kill()
        return False


def ping_ip(ip):
    ping_cmd.append(ip)
    ping_process = Popen(
        ping_cmd,
        stdout=PIPE,
        stderr=DEVNULL,
        text=True
    )
    result = check_ping_process(ping_process)
    return result


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):
            print({ip, result})
            ping_results.append({ip, result})
    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)

monitor_network_devices(ip_list)

该程序的目标是查明网络设备是否可 ping 通。我正在运行 main.py 文件,它给出了错误的结果。我尝试debug,似乎是线程的问题,但我无法解决它。

任何帮助将不胜感激

python multithreading subprocess concurrent.futures
1个回答
0
投票

一些观察

  • 如前所述,您不断向

    ping_cmd
    添加更多内容,您的命令将拥有越来越多的 IP 地址。最好每次都构建一个新命令,而不是追加到
    ping_cmd
    列表

  • 考虑这条线

      is_successes = findall("TTL", out)
    

    我查看 Linux 的输出,它看起来像这样:

      PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
      64 bytes from 192.168.1.1: icmp_seq=1 ttl=63 time=11.9 ms
      64 bytes from 192.168.1.1: icmp_seq=2 ttl=63 time=5.18 ms
    
      --- 192.168.1.1 ping statistics ---
      2 packets transmitted, 2 received, 0% packet loss, time 1024ms
      rtt min/avg/max/mdev = 5.182/8.541/11.901/3.359 ms
    

    在您的代码中,您搜索 TTL(大写),这将始终导致

    False
    。此外,要搜索文本,您不需要使用正则表达式:

      is_success = "ttl" in out
    
  • 由于您没有发布

    utilities
    包裹的内容,我不知道
    PACKET_COUT
    等值是什么

  • 处理多线程时,最好使用

    logging
    而不是print,因为前者是线程安全的,而后者不是。

这样,这是我提出的解决方案

# ping.py
import logging
import subprocess
from concurrent.futures import ThreadPoolExecutor

logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s | %(levelname)s | %(threadName)-15s | %(funcName)-18s | %(message)s",
)


def ping_ip(ip):
    ping_command = ["ping", "-c1", ip]
    logging.debug("Execute command %r", ping_command)
    completed_process = subprocess.run(
        ping_command,
        text=True,
        capture_output=True,
        check=False,
    )
    success = completed_process.returncode == 0
    logging.debug("%s -> %r", ip, success)
    return success


def ping_ip_list(ip_list):
    with ThreadPoolExecutor() as executor:
        out = dict(zip(ip_list, executor.map(ping_ip, ip_list)))
    return out
© www.soinside.com 2019 - 2024. All rights reserved.