Closed arkrow closed 1 year ago
I would consider this a bug.
IIRC, this was a problem on Linux with Python 2, but with the transition to Python 3, this was solved. I wasn't aware that this is still a problem with Windows.
I'm wondering that this didn't come up earlier though, because threading.Event
is also used in sounddevice.wait()
, which should be in common use, I guess.
Thanks for replying. Some additional investigation shows that it is indeed an issue with current python versions (as per the current open issue: https://bugs.python.org/issue35935). Thankfully, the workaround mentioned by a user in the thread works, and can be used until the issue is officially addressed in a later python release.
In the code example above, adding a signal handler for SIGINT before the event.wait()
call fixes this issue:
with stream:
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
print(f'Now playing {args.filename}. Ctrl+C to stop playback.')
event.wait() # Wait until playback is finished
Edit:
signal.signal(signal.SIGINT, signal.SIG_DFL)
will exit the program instead of raising a desired KeyboardInterrupt event to handle. An alternative workaround I discovered is by setting a small timeout to the wait function in a loop, e.g.
with stream:
print(f'Now playing {args.filename}. Ctrl+C to stop playback.')
while not event.wait(0.5): # 0.5 second timeout to handle interrupts in-between
pass
This workaround does not seem to affect playback from my testing and raises a KeyboardInterrupt when triggered. Although I'm sure there are better implementations, (perhaps one that avoids blocking the main thread), this workaround seems to be the simplest effective solution--provided that there are no unintended side-effects.
I'm currently trying to use the sounddevice library for A-B repeat style looping through the terminal. As such, playback is infinite until the user interrupts, usually with a Ctrl+C KeyboardInterrupt, which then should stop playback. This works as expected on Linux, however on Windows, this is not the case. The only way to interrupt playback on Windows is by terminating the python process in task manager.
The
wait()
function ofthreading.Event()
may be the culprit here. Onceevent.wait()
is triggered in the code example below (for playback), all signals and interrupts (including the critical KeyboardInterrupt for my use case) are blocked until the thread event is complete. This can be observed if a timeout is set in event.wait(); any KeyboardInterrupts invoked will be processed after the thread is 'unblocked'. Any attempted workaround relating to signal handling did not work, as KeyboardInterrupt is not raised until the event timeouts or its internal flag is set (normally, by completing playback, which in this case, is not possible).Is this a bug in the python interpreter (a similar issue has been raised before: https://bugs.python.org/issue8844), or am I overlooking something? Is there a possible workaround that would work here?
Here's a minimal example based on the
play_file.py
example provided in the docs. Code changes are highlighted using comments and additional line breaks. Strangely, the problem is also present in the originalplay_file.py
example but not inplay_long_file.py
, despite both usingevent.wait()
.Environment details: