This is my script
import threading import os class Say(threading.Thread): def __init__(self, cmd): super(Say, self).__init__() self.cmd = cmd def run(self): os.system(self.cmd) t1 = Say("afplay /System/Library/Sounds/Tink.aiff") t2 = Say("afplay /System/Library/Sounds/Ping.aiff") t1.start() print("a") t2.start() print("b")
It appears that both starts are executed immediately. However, the sounds are not played in parallel but one after the other.
When running the following shell script
afplay /System/Library/Sounds/Tink.aiff & afplay /System/Library/Sounds/Ping.aiff &
both sounds play at the same time. What makes Python run the commands sequentially instead of parallel?
I’m using Big Sur with with the standard Python (2.7).
Advertisement
Answer
I suspect the issue here is Python’s Global Interpreter Lock (GIL). In particular I’m guessing that when os.system
is called in t1
, the GIL locks and doesn’t unlock until the command returns, preventing t2
from running any python code.
If I replace
os.system(self.cmd)
with
subprocess.Popen(['bash', '-c', self.cmd])
then the problem goes away.
For that matter, since you are spawning separate processes at any event and doing nothing with their output, there is no point in creating all these threads; you can get the same effect by replacing your entire code sample with
import subprocess subprocess.Popen(['bash', '-c', "afplay /System/Library/Sounds/Tink.aiff"]) subprocess.Popen(['bash', '-c', "afplay /System/Library/Sounds/Ping.aiff"])