check output from CalledProcessError

后端 未结 6 698
心在旅途
心在旅途 2020-12-02 15:11

I am using subprocess.check_output from pythons subprocess module to execute a ping command. Here is how I am doing it:

output = subprocess.check_output([\"p         


        
相关标签:
6条回答
  • 2020-12-02 15:52

    This will return true only if host responds to ping. Works on windows and linux

    def ping(host):
        """
        Returns True if host (str) responds to a ping request.
        NB on windows ping returns true for success and host unreachable
        """
        param = '-n' if platform.system().lower()=='windows' else '-c'
        result = False
        try:
            out = subprocess.check_output(['ping', param, '1', host])
            #ping exit code 0
            if 'Reply from {}'.format(host) in str(out):
                result = True          
        except  subprocess.CalledProcessError:
            #ping exit code not 0
                result = False
        #print(str(out))
        return result
    
    0 讨论(0)
  • 2020-12-02 16:05

    I ran into the same problem and found that the documentation has example for this type of scenario (where we write STDERR TO STDOUT and always exit successfully with return code 0) without causing/catching an exception.

    output = subprocess.check_output("ping -c 2 -W 2 1.1.1.1; exit 0", stderr=subprocess.STDOUT, shell=True)
    

    Now, you can use standard string function find to check the output string output.

    0 讨论(0)
  • 2020-12-02 16:07

    Thanx @krd, I am using your error catch process, but had to update the print and except statements. I am using Python 2.7.6 on Linux Mint 17.2.

    Also, it was unclear where the output string was coming from. My update:

    import subprocess
    
    # Output returned in error handler
    try:
        print("Ping stdout output on success:\n" + 
               subprocess.check_output(["ping", "-c", "2", "-w", "2", "1.1.1.1"]))
    except subprocess.CalledProcessError as e:
        print("Ping stdout output on error:\n" + e.output)
    
    # Output returned normally
    try:
        print("Ping stdout output on success:\n" + 
               subprocess.check_output(["ping", "-c", "2", "-w", "2", "8.8.8.8"]))
    except subprocess.CalledProcessError as e:
        print("Ping stdout output on error:\n" + e.output)
    

    I see an output like this:

    Ping stdout output on error:
    PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
    
    --- 1.1.1.1 ping statistics ---
    2 packets transmitted, 0 received, 100% packet loss, time 1007ms
    
    
    Ping stdout output on success:
    PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
    64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=37.8 ms
    64 bytes from 8.8.8.8: icmp_seq=2 ttl=59 time=38.8 ms
    
    --- 8.8.8.8 ping statistics ---
    2 packets transmitted, 2 received, 0% packet loss, time 1001ms
    rtt min/avg/max/mdev = 37.840/38.321/38.802/0.481 ms
    
    0 讨论(0)
  • 2020-12-02 16:13

    If you want to get stdout and stderr back (including extracting it from the CalledProcessError in the event that one occurs), use the following:

    import subprocess
    
    command = ["ls", "-l"]
    try:
        output = subprocess.check_output(command, stderr=subprocess.STDOUT).decode()
        success = True 
    except subprocess.CalledProcessError as e:
        output = e.output.decode()
        success = False
    
    print(output)
    

    This is Python 2 and 3 compatible.

    If your command is a string rather than an array, prefix this with:

    import shlex
    command = shlex.split(command)
    
    0 讨论(0)
  • 2020-12-02 16:15

    According to the Python os module documentation os.popen has been deprecated since Python 2.6.

    I think the solution for modern Python is to use check_output() from the subprocess module.

    From the subprocess Python documentation:

    subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False) Run command with arguments and return its output as a byte string.

    If the return code was non-zero it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute and any output in the output attribute.

    If you run through the following code in Python 2.7 (or later):

    import subprocess
    
    try:
        print subprocess.check_output(["ping", "-n", "2", "-w", "2", "1.1.1.1"])
    except subprocess.CalledProcessError, e:
        print "Ping stdout output:\n", e.output
    

    You should see an output that looks something like this:

    Ping stdout output:
    
    Pinging 1.1.1.1 with 32 bytes of data:
    Request timed out.
    Request timed out.
    
    Ping statistics for 1.1.1.1:
    Packets: Sent = 2, Received = 0, Lost = 2 (100% loss),
    

    The e.output string can be parsed to suit the OPs needs.

    If you want the returncode or other attributes, they are in CalledProccessError as can be seen by stepping through with pdb

    (Pdb)!dir(e)   
    
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__',
     '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__',
     '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
     '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 
     '__unicode__', '__weakref__', 'args', 'cmd', 'message', 'output', 'returncode']
    
    0 讨论(0)
  • 2020-12-02 16:16

    In the list of arguments, each entry must be on its own. Using

    output = subprocess.check_output(["ping", "-c","2", "-W","2", "1.1.1.1"])
    

    should fix your problem.

    0 讨论(0)
提交回复
热议问题