pythonstdinpopenkillomxplayer

python how to kill a popen process, shell false [why not working with standard methods]


I'm trying to kill a subprocess started with:

playing_long = Popen(["omxplayer", "/music.mp3"], stdout=subprocess.PIPE)

and after a while

pid = playing_long.pid
playing_long.terminate()
os.kill(pid,0)
playing_long.kill()

Which doesn't work. Neither the solution pointed out here

How to terminate a python subprocess launched with shell=True

Noting that I am using threads, and it is not recommended to use preexec_fn when you use threads (or at least this is what I read, anyway it doesn't work either).

Why it is not working? There's no error message in the code, but I have to manually kill -9 the process to stop listening the mp3 file.

Thanks

EDIT: From here, I have added a wait() after the kill(). Surprisingly, before re-starting the process I check if this is still await, so that I don't start a chorus with the mp3 file.

EDIT2: The problem is that omxplayer starts a second process that I don't kill, and it's the responsible for the actual music.

And it prints 'NoneType' object has no attribute 'write'. Even when using this code immediately after starting the popen process, it fails with the same message

playing_long = subprocess.Popen(["omxplayer", "/home/pi/Motion_sounds/music.mp3"], stdout=subprocess.PIPE)
time.sleep(5)
playing_long.stdin.write('q')
playing_long.stdin.flush()

EDIT3: The problem then was that I wasn't establishing the stdin line in the popen line. Now it is

playing_long = subprocess.Popen(["omxplayer", "/home/pi/Motion_sounds/music.mp3"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
time.sleep(5)
playing_long.stdin.write(b'q')
playing_long.stdin.flush()

*needing to specify that it is bytes what I write in stdin


Solution

  • Final solution then (see the process edited in the question):

    playing_long = subprocess.Popen(["omxplayer", "/home/pi/Motion_sounds/music.mp3"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    time.sleep(5)
    playing_long.stdin.write(b'q')
    playing_long.stdin.flush()