我正在使用python subprocess.run()处理某些命令。我想捕获输出/错误/返回码,并且如果命令被阻止,希望超时。 代码很简单:
cmd = "ping 1.1.1.1 -n 5"
subprocess.run(cmd, shell=True, timeout=2)
但是结果使我感到困惑,为什么会抛出两个异常?
Python 3.6.8 (default, Jan 14 2019, 11:02:34)
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> cmd = "ping 1.1.1.1 -n 5"
>>> subprocess.run(cmd, shell=True, timeout=2)
PING 5 (0.0.0.5) 56(124) bytes of data.
Traceback (most recent call last):
File "/usr/lib/python3.6/subprocess.py", line 425, in run
stdout, stderr = process.communicate(input, timeout=timeout)
File "/usr/lib/python3.6/subprocess.py", line 863, in communicate
stdout, stderr = self._communicate(input, endtime, timeout)
File "/usr/lib/python3.6/subprocess.py", line 1560, in _communicate
self.wait(timeout=self._remaining_time(endtime))
File "/usr/lib/python3.6/subprocess.py", line 1469, in wait
raise TimeoutExpired(self.args, timeout)
subprocess.TimeoutExpired: Command 'ping 1.1.1.1 -n 5' timed out after 1.999514610040933 seconds
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/subprocess.py", line 430, in run
stderr=stderr)
subprocess.TimeoutExpired: Command 'ping 1.1.1.1 -n 5' timed out after 2 seconds
>>>
答案 0 :(得分:1)
您没有处理subprocess.run()的异常。 Python documentation for subprocess包含一个类似的示例,并且还显示了回溯:
>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
由于您没有处理该异常,因此python在发生故障时会给您回溯。由于您有意寻找异常(TimeoutExpired),因此需要对其进行处理。这是您的命令的示例:
import sys
import subprocess
f = open('output.txt', 'w') # store stdout
g = open('error.txt', 'w') # store stderr
cmd = "ping 8.8.8.8 -n -c 5"
try:
subprocess.run(cmd, shell=True, check=False, stdout=f, stderr=g timeout=2)
except subprocess.TimeoutExpired as t:
print("Timeout expired!")
print(t.timeout)
输出是:
Timeout expired!
2
2是超时阈值-subprocess.TimeoutExpired还有其他可以打印的属性:
cmd
Command that was used to spawn the child process.
timeout
Timeout in seconds.
output
Output of the child process if it was captured by run() or check_output(). Otherwise, None.
stdout
Alias for output, for symmetry with stderr.
stderr
Stderr output of the child process if it was captured by run(). Otherwise, None.
我在本地目录中创建了output.txt和error.txt来捕获stdout和stderr,这回答了您询问的另一部分,如何记录命令的输出和错误以及超时。
答案 1 :(得分:0)
如果您想要一定数量的ping,则选项为'c'。如果您希望ping命令超时,则选项为“ w”。
>>> subprocess.run("ping -w 3 127.0.0.1".split())
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.100 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.125 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.052 ms
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.052/0.092/0.125/0.031 ms
CompletedProcess(args=['ping', '-w', '3', '127.0.0.1'], returncode=0)
包装try / except表示是否有多个异常无关紧要:
>>> try:
... subprocess.run("ping 127.0.0.1".split(), timeout=2)
... except subprocess.TimeoutExpired:
... print('handle')
...
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.094 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.163 ms
handle