我知道在 SO 上有很多类似的问题,例如 this one或 this one也许还有几个,但它们似乎都不适用于我的特定情况。我对 subprocess.Popen()
的工作原理缺乏了解也无济于事。
我想实现的是:启动一个子进程(一个命令行广播播放器),它也向终端输出数据,也可以接收输入——等待一段时间——终止子进程——退出shell。我在 OSX 10.9 上运行 python 2.7
案例 1. 这会启动广播播放器(但只有音频!),终止进程,退出。
import subprocess
import time
p = subprocess.Popen(['/bin/bash', '-c', 'mplayer http://173.239.76.147:8090'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=False,
stderr=subprocess.STDOUT)
time.sleep(5)
p.kill()
案例 2. 这会启动广播播放器,输出广播名称、歌曲、比特率等信息,并接受输入。它终止了子进程,但它从不存在外壳,即使在使用“Ctrl-C”后终端也变得不可用。
p = subprocess.Popen(['/bin/bash', '-c', 'mplayer http://173.239.76.147:8090'],
shell=False)
time.sleep(5)
p.kill()
关于如何做的任何想法?我什至在考虑如果没有其他选择的话,是否可以为子进程打开一个 slave-shell (当然这也是我不知道的事情)。谢谢!
最佳答案
似乎 mplayer
使用了 curses
库,当 kill()
或 terminate()
出于某种原因,它无法正确清理库状态。
要恢复终端状态,您可以使用reset
命令。
演示:
import subprocess, time
p = subprocess.Popen(['mplayer', 'http://173.239.76.147:8090'])
time.sleep(5)
p.terminate()
p.wait() # important!
subprocess.Popen(['reset']).wait()
print('Hello, World!')
原则上也应该可以使用 stty sane
,但它对我来说效果不佳。
正如 Sebastian 指出的那样,上面的代码(现在已添加)中缺少一个 wait()
调用。使用此 wait()
调用 and 使用 terminate()
终端不会被弄乱(因此不应该有任何需要用于重置
)。
如果没有 wait()
,我有时会遇到 python 进程和 mplayer
之间混合输出的问题。
此外,正如 Sebastian 所指出的,mplayer
的一个特定解决方案是向 mplayer
的标准输入发送一个 q
以退出
我保留使用 reset
的代码,因为它可以与使用 curses
库的任何程序一起使用,无论它是否正确地拆除了库或不,因此它可能在其他不可能干净退出的情况下很有用。
关于python - 终止子进程后 Shell 挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22899568/