我在Python中编写了一个小的gui-frontend,让用户可以播放互联网广播频道。该程序使用Pythons subprocess()来启动mplayer以调入一个频道,例如:
runn = "mplayer http://77.111.88.131:8010"
p = subprocess.Popen(runn, shell=True)
pid = int(p.pid)
wait = os.waitpid(p.pid, 1)
然后保存p.pid,当用户想要停止监听时,使用以下代码:
os.kill(p.pid, 9)
这在OpenSUSE中完美运行,但在Ubuntu中不行。似乎Ubuntu实际上启动了两个独立的进程。终端输出:
Opensuse 11.3:
$ pgrep mplayer
22845
Ubuntu 10.04:
$ pgrep mplayer
22846
22847
这在运行其他程序时也适用。有谁知道为什么?我真的希望这个应用程序在所有发行版上运行,所以任何帮助都深受赞赏。
答案 0 :(得分:6)
试试这个:
p = subprocess.Popen(runn.split(), shell=False)
我猜这是怎么回事......
当您说shell=True
子进程实际启动此命令sh -c "your string"
时。然后sh
命令解释您的字符串并运行该命令,就像您在shell提示符下输入的那样(或多或少)。通常这会导致两个过程。一个是sh -c "your string"
,另一个是孩子,your string
。
sh
的某些版本具有优化,在某些条件下,它们会自动exec
命令。如果它是最后一个sh
将要运行的命令并且sh
没有其他理由可以坚持下去,他们会这样做。使用sh -c
运行命令时,这几乎总会导致调用sh
将其自身替换为正在运行的命令,从而导致一个进程。
在我看来,用subprocess.Popen
调用shell=True
是一个非常非常糟糕的主意。通过执行此操作,您将面临大量安全问题,并且通常不太可预测的行为,因为shell元字符由sh -c
解释。
答案 1 :(得分:1)
我没有确切的答案,但有几种方法可以调查:
使用pstree
检查进程之间的父/子关系。
使用ps -awux
查看所有进程的完整命令行参数。
请注意,使用shell=True
启动一个启动/bin/bash
的shell进程(例如mplayer
)。这可能是另一种调查途径。两个系统都使用相同的shell吗?
两个系统都使用相同版本的mplayer吗?蟒蛇?
答案 2 :(得分:0)
subprocess.Popen返回带有several useful methods的Popen对象。直接使用os.kill来终止事情可能是个坏主意......
如果您使用Popen对象的p.terminate()或p.kill()方法会发生同样的事情吗?