Python子进程Popen.terminate()仍然卡在wait()上



我正在尝试使用RPi实现无线电播放器。目标是设置一个播放列表,并在播放列表填充后开始播放。一旦停止代码被执行,播放器和无线电进程应该退出。

无线电进程很好地终止,但播放器进程仍然保持等待状态,即使在调用terminate之后。如果再次调用停止代码,则播放器进程终止

尝试的东西:

  1. 重新排序等待命令(player,radio)/(radio,player)
  2. 类似的重新排序终止命令
  3. 使用kill而不是terminate挂起RPi

播放器代码:

while playlist:
    player = subprocess.Popen(
            ["avconv", "-i", "Music/%s" % playlist[0], "-f", "s16le", "-ar", 
            "22.05k", "-ac", "1", "-"], stdout=subprocess.PIPE)
    radio = subprocess.Popen(["./pifm", "-", freq], stdin=player.stdout)
    radio.wait()
    print "************ exiting from radio :)"
    player.wait()
    print "************ exiting from player :)"
    playlist.pop(0)
player = None
radio = None

播放器停止代码(从另一个线程调用):

print "************ stop requested"
if radio and radio.poll() is None:
    print "************ terminating radio :)"
    radio.terminate()
if player and player.poll() is None:
    print "************ terminating player :)"
    player.terminate()

选择:

另一种选择是为播放器设置一个持久的接收器和随需应变的过程

def start_radio():
    global radio
    radio = subprocess.Popen(["./pifm"...], stdin=subprocess.PIPE)
def play():
    global player
    while playlist and radio:
        player = subprocess.Popen(["avconv"...], stdout=radio.stdin)
        player.wait()
        playlist.pop(0)
def stop():
   if player and player.poll() is None:
      print "************ terminating player :)"
      player.terminate()

但是在这种情况下,调用player.terminate()关闭播放器,同时在广播进程中重复播放最后一个数据包(如卡住的记录)。这个卡住的记录一直播放,直到我打开一个新的播放器或终止收音机。

Sebastian提到,使用player.stdout.close()是可行的。完整的代码库在这里发布https://github.com/hex007/pifm_server

所以最后的代码看起来像这样
while playlist:
    player = subprocess.Popen(
            ["avconv", "-i", "Music/%s" % playlist[0], "-f", "s16le", "-ar", 
            "22.05k", "-ac", "1", "-"], stdout=subprocess.PIPE)
    radio = subprocess.Popen(["./pifm", "-", freq], stdin=player.stdout)
    player.stdout.close()
    radio.wait()
    player.wait()
    if stop_requested:
        stop_requested = False
        break
    playlist.pop(0)
player = None
radio = None

和停止代码:

stop_requested = True
if radio and radio.poll() is None:
    radio.terminate()
if player and player.poll() is None:
    player.terminate()

相关内容

  • 没有找到相关文章

最新更新