我正在使用Python 2.7开发一个小工具并使用子进程模块。我正在使用此模块使用其check_output
函数在远程设备上运行命令。可能存在远程设备无法运行的情况,因此我收到以下响应:
Timeout: No Response from 10.xxx.xxx.xxx
以下是我的代码:
try:
x=subprocess.check_output(command, shell=True)
except Exception:
print ("Some issues in fetching details")
exit()
else:
print (x)
我想将超时置于此函数中,以便在一定时间后没有收到响应,我的代码进入Exception部分并打印给定的消息。我尝试在check_output
命令中使用timeout参数,但在使用timeout参数运行脚本后,它会立即打印Exception部分中给出的消息。
我尝试了什么:
try:
x=subprocess.check_output(command, shell=True, timeout=5)
except Exception:
print ("Some issues in fetching details")
exit()
else:
print (x)
答案 0 :(得分:3)
我的猜测是你在Python 2中运行你的代码。
如果是这种情况,subprocess.check_output()
不接受timeout
参数,该函数将立即失败:
TypeError: __init__() got an unexpected keyword argument 'timeout'
但是,因为您正在捕获所有异常并打印通用消息,所以您没有看到实际异常,并且您认为命令会立即超时。
解决此问题的一种方法是在Python 3中运行代码。
无论您是运行Python 2还是3,我建议您不要捕获所有异常,或者至少打印异常值以便您可以看到实际原因,例如
try:
x=subprocess.check_output(command, shell=True, timeout=5)
except subprocess.TimeoutExpired as exc:
print("Command timed out: {}".format(exc))
exit()
else:
print (x)
显式检查超时异常。所有其他异常都照常传播,因此不会被“全部捕获”代码掩盖。或者,
try:
x=subprocess.check_output(command, shell=True, timeout=5)
except Exception as exc:
print("Command failed: {}".format(exc))
exit()
else:
print (x)
但前者是首选。
修改强>
OP无法使用Python 3.如果您使用的是Linux,则可以使用timeout
命令,例如
x = subprocess.check_output('timeout 5 {}'.format(command), shell=True)
在超时时,这将引发具有特定退出状态值124的异常:
subprocess.CalledProcessError: Command 'timeout 5 sleep 10' returned non-zero exit status 124
顺便说一下,您不应该使用shell=True
选项,因为文档中提到了安全隐患。相反,您应该将字符串列表传递给check_output()
,如下所示:
from shlex import shlex
command = shlex('timeout 5 {}'.format(command))
try:
x = subprocess.check_output(command)
except subprocess.CalledProcessError as exc:
if exc.returncode == 124:
print "Command timed out"
else:
raise
如果您正在使用其他操作系统(或者您不想使用timeout
),则可以在单独的线程中运行子进程,并在需要时让主线程将其计时。有关如何执行此操作的详细信息,请参阅另一个问题Using module 'subprocess' with timeout。
答案 1 :(得分:2)
Python 2.7不支持timeout参数。您可以使用EasyProcess。这是一个位于子进程模块之上的层,非常易于使用。