首頁  >  文章  >  後端開發  >  我正在使用帶有線程的 subprocess.Popen 類,但它對我不起作用

我正在使用帶有線程的 subprocess.Popen 類,但它對我不起作用

WBOY
WBOY轉載
2024-02-22 13:13:11679瀏覽

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

問題內容

我有以下檔案:

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,似乎是線程的問題,但無法解決。

任何幫助將不勝感激


正確答案


一些觀察

  • 如前所述,您不斷向 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

以上是我正在使用帶有線程的 subprocess.Popen 類,但它對我不起作用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除