使用subprocess的wait()和poll()

32 投票
2 回答
93107 浏览
提问于 2025-04-15 23:41

我正在尝试写一个小应用程序,使用的是 subprocess 模块。

我的程序会调用一个外部的 Bash 命令,这个命令需要一些时间来处理。在这段时间里,我想给用户显示一系列消息,比如:

正在处理,请稍等...
输出结果是 foo()

我该如何使用 Popen.wait()Popen.poll() 来实现这个功能呢?我听说需要用到 Popen.returncode,但我不知道怎么主动检查状态。

2 个回答

33

@extraneon的回答有点反了。其实,wait()poll()这两个方法都会在进程结束时返回它的退出代码。如果进程还在运行,poll()会返回None,而wait()则会一直等到进程结束才会继续往下执行:

可以查看以下页面了解更多信息: https://docs.python.org/3.4/library/subprocess.html#popen-objects

Popen.poll()

检查子进程是否已经结束。如果结束了,就设置并返回返回代码属性。

Popen.wait()

等待子进程结束。如果结束了,就设置并返回返回代码属性。

44

无论是 wait()(指定了 timeout)还是 poll(),如果进程还没有结束,它们都会返回 None;如果进程已经结束,它们会返回其他东西(我想是一个整数,表示退出代码,最好是0)。

编辑:

wait()poll() 的行为是不同的:

  • wait(没有 timeout 参数)会阻塞,直到进程完成。
  • wait 加上 timeout 参数会等待 timeout 秒,看看进程是否完成。如果没有完成,它会抛出 TimeoutExpired 异常。如果你捕获了这个异常,你可以选择继续执行,或者再调用一次 wait
  • poll 总是会立即返回。它实际上是做了一个超时时间为0的等待,如果进程还没完成,就返回 None
  • 无论是 wait 还是 poll,如果进程已经完成,popen 对象的 returncode 会被设置(否则是 None - 你可以通过调用 waitpoll 来轻松检查),函数的返回值也会是进程的返回代码。

</编辑>

所以我觉得你应该做类似这样的事情:

while myprocess.poll() is None:
    print("Still working...")
    # sleep a while

要注意,如果 bash 脚本产生了很多输出,你必须使用 communicate() 或类似的方法,以防 stdoutstderr 被填满。

撰写回答