杀死子进程后外壳挂起

ska*_*sie 5 python subprocess

我知道在 SO 上有很多类似的问题,比如这个或这个,也许还有更多,但似乎没有一个适用于我的特定情况。我对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()
Run Code Online (Sandbox Code Playgroud)

案例 2. 这将启动收音机播放器,输出诸如收音机名称、歌曲、比特率等信息并接受输入。它终止子进程,但它从不存在 shell,即使使用“Ctrl-C”,终端也无法使用。

p = subprocess.Popen(['/bin/bash', '-c', 'mplayer http://173.239.76.147:8090'],
                     shell=False)
time.sleep(5)
p.kill()
Run Code Online (Sandbox Code Playgroud)

关于如何做到这一点的任何想法?我什至在想,如果没有其他选择,是否有可能为子进程打开一个slave-shell(当然这也是我不知道的事情)。谢谢!

Bak*_*riu 5

似乎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!')
Run Code Online (Sandbox Code Playgroud)

原则上它也应该可以使用stty sane,但它对我来说效果不佳。


正如 Sebastian 指出的那样,wait()上面的代码中缺少一个调用(现已添加)。通过这个wait()调用和使用terminate()终端不会被搞砸(所以不应该有任何需要reset)。

如果没有,wait()我有时会在 python 进程和mplayer.

此外,mplayer正如塞巴斯蒂安所指出的,特定于 的解决方案是将 a 发送q到 的标准输入mplayer以退出它。

我留下了使用的代码,reset因为它适用于任何使用curses库的程序,无论它是否正确地拆除了库,因此它可能在无法干净退出的其他情况下有用。