[英]Why are two exceptions thrown when using subprocess.run()?
我正在使用 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
>>>
您没有处理 subprocess.run() 的异常。 子流程的Python 文档包含一个类似的示例,它还显示了回溯:
>>> 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)
来自这个的output是:
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,这回答了你的另一部分问题,如何记录命令的 output 和错误以及超时。
如果您想要一定数量的 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
我遇到过类似的问题。 但我自己造成的 - 代表好的 IDE 建议:-D。 我已经正确处理了 TimeoutExpired,但在 except 块的末尾,我引发了另一个异常并使用from
。 它也上升了 TimeoutExpired,但没有再次处理。
try:
check_output(...)
except subprocess.TimeoutExpired as problem:
# some logging stuff
raise ConnectionError("Some useful info") from problem
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.