Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python subprocess poll()不会返回None,即使Popen仍在运行_Python_Timeout_Subprocess_Pipe_Python 2.4 - Fatal编程技术网

python subprocess poll()不会返回None,即使Popen仍在运行

python subprocess poll()不会返回None,即使Popen仍在运行,python,timeout,subprocess,pipe,python-2.4,Python,Timeout,Subprocess,Pipe,Python 2.4,我有一个python脚本,它使用while循环和sleep(如下所示)执行带超时的linux命令 fout = tempfile.TemporaryFile() try: p = subprocess.Popen(["/bin/bash","-c", options.command], bufsize=-1, shell=False, preexec_fn=os.setsid, stdin=subprocess.PIPE, stdout=fout, stderr=subprocess.P

我有一个python脚本,它使用while循环和sleep(如下所示)执行带超时的linux命令

fout = tempfile.TemporaryFile()
try:
    p = subprocess.Popen(["/bin/bash","-c", options.command], bufsize=-1, shell=False, preexec_fn=os.setsid, stdin=subprocess.PIPE, stdout=fout, stderr=subprocess.PIPE)
except:
    sys.exit(UNEXPECTED_ERROR)
if options.timeout:
    print "options.timeout = %s" % options.timeout
    elapsed = 0
    time.sleep(0.1) # This sleep is for the delay between Popen and poll() functions
    while p.poll() is None:
        time.sleep(1)
        elapsed = elapsed + 1
        print "elapsed = %s" % elapsed
        if elapsed >= options.timeout:
            # TIMEDOUT
            # kill all processes that are in the same child process group
            # which kills the process tree
            pgid = os.getpgid(p.pid)    
            os.killpg(pgid, signal.SIGKILL)
            p.wait()
            fout.close()
            sys.exit(TIMEOUT_ERROR)
            break
else:
    p.wait()

fout.seek(0) #rewind to the beginning of the file
print fout.read(),
fout.close()
sys.exit(p.returncode)

$ time myScript -c "cat file2" 2>&1 -t 5
options.timeout = 5
elapsed = 1

real    0m11.811s
user    0m0.046s
sys     0m1.153s

我的问题是,在上述情况下,即使超时为5秒,cat仍会继续,直到完成。我是不是遗漏了什么?请帮助。

除了我在代码中看到的问题之外

  • 使用
    stdin=subprocess.PIPE
    stderr=subprocess.PIPE
    调用
    Popen()。但你从来不会处理这些管道。使用类似于
    cat file2
    的命令,这应该没问题,但可能会导致问题
我可以发现一个潜在的错误行为:你可能混淆了缩进(如你问题的第一个版本)。假设您拥有以下各项:

while p.poll() is None:
    time.sleep(1)
    elapsed = elapsed + 1
    print "elapsed = %s" % elapsed
    if elapsed >= options.timeout:
        # TIMEDOUT
        # kill all processes that are in the same child process group
        # which kills the process tree
        pgid = os.getpgid(p.pid)    
        os.killpg(pgid, signal.SIGKILL)
    p.wait()
    fout.close()
    sys.exit(TIMEOUT_ERROR)
    break

您没有达到超时阈值,但是由于缩进错误而调用了
p.wait()
。不要混淆标签和空格;PEP 8建议只使用空格和4列的缩进深度。

它在Ubuntu上的效果与预期一样:

$ /usr/bin/ssh root@localhost -t 'sync && echo 3 > /proc/sys/vm/drop_caches'
$ /usr/bin/time python2.4 myscript.py 'cat big_file'
timeout
done
0.01user 0.63system 0:05.16elapsed 12%CPU 

$ /usr/bin/ssh root@localhost -t 'sync && echo 3 > /proc/sys/vm/drop_caches'
$ /usr/bin/time cat big_file >/dev/null
0.02user 0.82system 0:09.93elapsed 8%CPU
它还可以使用shell命令:

$ /usr/bin/time python2.4 myscript.py 'while : ; do sleep 1; done'
timeout
done
0.02user 0.00system 0:05.03elapsed 0%CPU
假设:

  • 由于系统时钟可能发生变化,您无法使用
    time.time()

  • time.clock()
    在Linux上不测量子时间

  • 我们不能在纯Python中模仿Python 3.3中的
    time.monotonic()
    由于
    ctypes在Python 2.4上不可用

  • 允许在休眠状态下生存,例如,如果超时时间为5秒,则在休眠前2秒+计算机唤醒后3秒

#/usr/bin/env python2.4
导入操作系统
输入信号
导入系统
导入临时文件
导入时间
从子流程导入Popen
类TimeoutExpired(异常):
通过
def wait(进程、超时、睡眠时间=.1):
对于x范围内的u(int(超时*1./_睡眠时间+.5)):
时间。睡眠(_sleep_time)#注意:假设它醒得不早
如果process.poll()不是无:
返回进程。等待()
raise TimeoutExpired#注意:超时精度不是很高
f=tempfile.TemporaryFile()
p=Popen([“/bin/bash”,“-c”,sys.argv[1]],stdout=f,preexec_fn=os.setsid,
关闭(fds=真)
尝试:
等待(p,超时=5)
除TimeoutExpired外:
打印>>sys.stderr,“超时”
os.killpg(os.getpgid(p.pid),signal.SIGKILL)
p、 等等
其他:
f、 搜索(0)
对于f中的行:
打印行,
f、 close()#删除它
打印>>sys.stderr,“完成”

我使用Python2.4.3在RHEL5.5上运行,我认为有可能
cat
将所有数据都放在输出流中,但您的终端速度太慢,无法读取所有数据。如果您尝试像:
while:;做回声“嗨”;睡眠1;完成
?您能详细说明一下您看到的内容吗?粘贴的输出看起来像是首次运行循环后退出的while循环。它似乎不应该进入超时代码。
$time my_script-c”while:;do echo“hi”;sleep 1;done“2>&1-t5选项。超时=5经过=1经过=2经过=3经过=4经过=5实际的0m5.155s用户0m0.039s系统0m0.012s
看起来在“hi”时超时情况下工作正常。你能详细说明一下在我的例子中发生了什么吗?在我的例子中,我做了一个100MB的文件,其中填充了/dev/zero@KurtStutsman我正在尝试cat一个100MB的文件,其中填充了/dev/zero。]<代码>$time cat file2 real 0m10.481s用户0m0.004s系统0m0.734s
我深表歉意<代码>轮询()
即使进程仍在运行,也不会返回None。这可能是一个新手问题,但如何以不同的方式处理stdin和stderr管道?如果您能给我指出如何处理管道的相关链接,这将有所帮助。我以前使用过带超时的pexpect,但遇到了一些问题,因为pexpect超时对系统时间变化很敏感。所以我求助于使用上面的python代码。我上面的问题是,如果子进程“cat”需要11秒来处理,为什么poll()函数只运行一次?我在脚本中检查了缩进。这不是问题所在。我仍然看到我的子进程在上面的while循环中运行了11秒。我试过这样的脚本
$ls-alrt file2
-rw-r--r--1根根根104857600 10月19日14:56 file2
$time cat file2
real 0m10.468s用户0m0.011s sys 0m0.710s
$time脚本“cat file2”
done real 0m11.360s用户0m0.152s sys 0m1.278smy文件2是通过此dd命令创建的
dd if=/dev/zero of=./file2 bs=100M count=1
感谢您的回复。你的脚本在5秒内没有超时。让我知道填充了/dev/zero的文件的cat是否与其他文件的行为不同,或者我是否丢失了something@yalkris:没有超时,因为
cat
在5秒之前完成。剩下的时间是在
中为f
循环中的行打印零字节(一次迭代,因为文件中没有换行符),在我的终端上没有可见的输出(尝试
cat-v file2
查看零字节)。如果将
脚本重定向到devnull,它应该在不到一秒的时间内结束:
超时时间“cat file2”>/dev/null
。如果愿意,可以限制整个脚本的执行时间(例如,只需调用自身)