I am using subprocess.Popen class with threads but it is not working for me

WBOY
Release: 2024-02-22 13:13:11
forward
691 people have browsed it

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

Question content

I have the following files:

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
Copy after login

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)
Copy after login

The goal of this program is to find out if a network device is pingable. I am running the main.py file and it is giving wrong results. I tried debugging and it seems to be a thread problem, but I can't solve it.

Any help would be appreciated


Correct answer


Some observations

  • As mentioned before, as you keep appending more content to ping_cmd, your command will have more and more ip addresses. It's better to build a new command each time instead of appending to the ping_cmd list

  • Consider this line

    is_successes = findall("ttl", out)
    Copy after login

    I look at the linux output and it looks like this:

    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
    Copy after login

    In your code, you search for ttl (uppercase), which will always result in false. Also, to search text you don't need to use regular expressions:

    is_success = "ttl" in out
    Copy after login
  • Since you didn't post the contents of the utilities package, I don't know what the packet_cout equivalent value is

  • When dealing with multi-threading, it is better to use logging instead of print, because the former is thread-safe, while the latter is not.

In this way, this is my proposed solution

# 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
Copy after login

The above is the detailed content of I am using subprocess.Popen class with threads but it is not working for me. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template