简体   繁体   English

如何在等待完成的Python子进程中将其杀死?

[英]How do you kill a Python subprocess while it's waiting to finish?

Trying to use Python subprocesses to play audio on a Raspberry Pi and kill the subprocess when a GPIO-connected button is pressed. 尝试使用Python子进程在Raspberry Pi上播放音频,并在按下GPIO连接按钮时杀死该子进程。

The issue I'm having is that the subprocess won't kill when there's a subprocess Popen.wait() command between playback files. 我遇到的问题是,在播放文件之间存在子进程Popen.wait()命令时,子进程不会终止。 If there's only one file to play, there's no need to wait for it to finish, and a p.kill() command works just fine. 如果只播放一个文件,则无需等待它完成,并且p.kill()命令可以正常工作。 As soon as a p.wait() is inserted so that the files don't play on top of each other, Popen.kill() no longer works. 一旦插入p.wait()以便文件不能相互播放,Popen.kill()将不再起作用。

Already tried using os.kill() in Kill a running subprocess call . 已经尝试在杀死正在运行的子进程调用中使用os.kill()。 Can't find any other resources about how subprocesses behave under Popen.wait(). 在Popen.wait()下找不到有关子进程行为的其他资源。 I'm looking for a way to force the aplay function in the code below to close on a button press at any time during the three play_wav commands in the second code snippet instead of having just one play_wav command. 我正在寻找一种方法来强制下面代码中的aplay函数在第二个代码段中的三个play_wav命令期间随时按一次按钮关闭,而不是只有一个play_wav命令。

Here's the play_wav function utilizing subprocess.Popen(): 这是利用subprocess.Popen()的play_wav函数:

# play wav file on the attached system sound device
def play_wav(wav_filename):
    global p
    msg = "playing " + wav_filename
    logger.debug(msg)
    p = subprocess.Popen(
        ['aplay','-i','-D','plughw:1', wav_filename],
        stdin = subprocess.PIPE,
        stdout = subprocess.PIPE,
        stderr = subprocess.STDOUT,
        shell = False
    )

Here's a snippet of code calling the play_wav function: 这是调用play_wav函数的代码片段:

# determine what to do when a button is pressed
def button_pressed(channel):
    global MENU
    btnval = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS) # check value of ADC
    if btnval > 980: # 1
        if p.poll() == None:
            p.kill()
        if MENU == 1:
            play_wav("/media/pi/WONDERPHONE/prompts/en/Menu1.wav")
            p.wait()
            play_wav("/media/pi/WONDERPHONE/stories/1/PersonalStory.wav")
            p.wait()
            play_wav("/media/pi/WONDERPHONE/prompts/en/returntomain.wav")

How I'm checking for button presses: 我如何检查按钮按下情况:

GPIO.add_event_detect(PRESSED, GPIO.RISING, callback=button_pressed, bouncetime=500) # look for button presses

From the subprocess module docs: subprocess模块文档:

Popen.wait() Popen.wait()

Wait for child process to terminate. 等待子进程终止。 Set and return returncode attribute. 设置并返回returncode属性。 Warning - This will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. 警告-使用stdout = PIPE和/或stderr = PIPE时,这将导致死锁,并且子进程会向管道生成足够的输出,从而阻塞等待OS管道缓冲区接受更多数据的等待。 Use communicate() to avoid that. 使用communication()可以避免这种情况。

Try using communicate() before you kill the subprocess 在终止子进程之前尝试使用communicate()

You can use terminal to do that. 您可以使用终端执行此操作。 ps aux | ps aux | grep taskname sudo kill -9 taskid grep taskname sudo kill -9 taskid

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM