Python subprocess.call not waiting for process to finish blender

Tak picture Tak · Apr 12, 2017 · Viewed 18.2k times · Source

I have a python script in blender where it has

subprocess.call(os.path.abspath('D:/Test/run-my-script.sh'),shell=True)

followed by many other code which depends on this shell script to finish. What happens is that it doesn't wait for it to finish, I don't know why? I even tried using Popen instead of call as shown:

p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),shell=True)
p1.wait()

and I tried using commuincate but it still didn't work:

p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),shell=True).communicate()

this shell script works great on MacOS (after changing paths) and waits when using subprocess.call(['sh', '/userA/Test/run-my-script.sh'])

but on Windows this is what happens, I run the below python script in Blender then once it gets to the subprocess line Git bash is opened and runs the shell script while blender doesn't wait for it to finish it just prints Hello in its console without waiting for the Git Bash to finish. Any help?

import bpy
import subprocess
subprocess.call(os.path.abspath('D:/Test/run-my-script.sh'),shell=True)
print('Hello')

Answer

joebeeson picture joebeeson · Jun 8, 2017

You can use subprocess.call to do exactly that.

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

Run the command described by args. Wait for command to complete, then return the returncode attribute.

Edit: I think I have a hunch on what's going on. The command works on your Mac because Macs, I believe, support Bash out of the box (at least something functionally equivalent) while on Windows it sees your attempt to run a ".sh" file and instead fires up Git Bash which I presume performs a couple forks when starting.

Because of this Python thinks that your script is done, the PID is gone.

If I were you I would do this:

  • Generate a unique, non-existing, absolute path in your "launching" script using the tempfile module.
  • When launching the script, pass the path you just made as an argument.
  • When the script starts, have it create a file at the path. When done, delete the file.
  • The launching script should watch for the creation and deletion of that file to indicate the status of the script.

Hopefully that makes sense.