Python 终止子进程(启动另一个进程)并重新启动它

2 投票
2 回答
1949 浏览
提问于 2025-04-29 05:48

我正在尝试写一个Python脚本,这个脚本会启动一个叫做livestreamer的程序(它会再启动一个叫做mplayer的程序),然后在10秒后结束这个程序或者它的子进程。下面是我现在的代码,但它不太好用,我觉得我知道问题出在哪里,但不知道怎么解决。

我认为问题在于,子进程启动了livestreamer,而livestreamer又启动了mplayer。Python并不知道mplayer的存在,所以无法关闭它。我该如何在10秒后同时结束livestreamer和mplayer,然后再以循环的方式重新启动它们呢?我使用的是Ubuntu 14.04(Linux)和Python 2.7.6。

import subprocess
import time
import os
import sys
import signal

url = "http://new.livestream.com/accounts/398160/events/3155348"
home = os.environ['HOME']

if not os.geteuid() == 0:
    if not os.path.exists('/%s/.config/livestreamer' % home):
        os.makedirs('/%s/.config/livestreamer' % home)
    lscfg = open('%s/.config/livestreamer/config' % home, 'w+')
    lscfg.write("player=mplayer -geometry 0%:0% -nomouseinput -loop 100 -noborder -fixed-vo")
    lscfg.close()

cmd = "livestreamer %s best --player-continuous-http --player-no-close" % url
while True:
    proc1 = subprocess.Popen(cmd.split(), shell=False)
    time.sleep(10)
    proc1.kill()

解决方案:

import subprocess
import time
import os
import sys
import signal

url = "http://new.livestream.com/accounts/398160/events/3155348"
home = os.environ['HOME']

if not os.geteuid() == 0:
    if not os.path.exists('/%s/.config/livestreamer' % home):
        os.makedirs('/%s/.config/livestreamer' % home)
    lscfg = open('%s/.config/livestreamer/config' % home, 'w+')
    lscfg.write("player=mplayer -geometry 0%:0% -nomouseinput -loop 100 -noborder -fixed-vo")
    lscfg.close()
cmd = "livestreamer %s best --player-continuous-http --player-no-close" % url
#restarting the player every 10th minute to catch up on possible delay
while True:
    proc1 = subprocess.Popen(cmd.split(), shell=False)
    time.sleep(600)
    os.system("killall -9 mplayer")
    proc1.kill()

如你所见,os.system("killall -9 mplayer")是用来结束mplayer进程的命令。

暂无标签

2 个回答

0

在你的代码中,你结束了livestreamer这个程序,但没有结束mplayer,所以mplayer会继续运行。

当你对你的子进程使用kill命令时,你实际上是发送了一个叫做SIGKILL的信号。除非这个子进程能够处理这个信号,否则它会很快关闭自己,但不会去结束它自己创建的子进程,所以mplayer会继续运行(可能会变成一个僵尸进程)。

你没有mplayer这个子进程的引用,但如果你能找到它的PID(进程ID),你就可以用os.kill(...)来结束它。

os.kill(process_pid, signal.SIGTERM)
0

使用 os.system("killall -9 mplayer") 是个简单的解决办法。不过要注意,这个方法会把所有的 mplayer 进程都杀掉。在我的情况下这没问题,但在其他情况下可能会有问题。

while True:
        proc1 = subprocess.Popen(cmd.split(), shell=False)
        time.sleep(600)
        os.system("killall -9 mplayer")
        proc1.kill()

撰写回答