Skip to content
Advertisement

Threads not running in parallel for a system command

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"])
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement