简体   繁体   English

Python subprocess.call没有等待进程完成blender

[英]Python subprocess.call not waiting for process to finish blender

I have a python script in blender where it has 我在blender中有一个python脚本

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. 接着是许多其他代码,依赖于这个shell脚本来完成。 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: 我甚至尝试使用Popen而不是如图所示的call

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: 我尝试使用commuincate但它仍然无法正常工作:

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']) 这个shell脚本在MacOS上运行得很好(在更改路径之后)并在使用subprocess.call(['sh', '/userA/Test/run-my-script.sh'])时等待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. 但是在Windows上发生了这种情况,我在Blender中运行下面的python脚本然后一旦它到达子进程行Git bash被打开并运行shell脚本而blender没有等待它完成它只是在其控制台中打印Hello无需等待Git Bash完成。 Any help? 有帮助吗?

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

You can use subprocess.call to do exactly that. 你可以使用subprocess.call来做到这一点。

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

Run the command described by args. 运行args描述的命令。 Wait for command to complete, then return the returncode attribute. 等待命令完成,然后返回returncode属性。

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. 该命令适用于你的Mac,因为Macs,我认为,开箱即用支持Bash( 至少功能相当于某些东西 ),而在Windows上,它会看到你试图运行“.sh”文件,而是启动我认为执行的Git Bash一对夫妇在开始时分叉。

Because of this Python thinks that your script is done, the PID is gone. 因为这个Python 认为你的脚本已经完成,所以PID已经消失了。

If I were you I would do this: 如果我是你,我会这样做:

  • Generate a unique, non-existing, absolute path in your "launching" script using the tempfile module. 使用tempfile模块在“启动”脚本中生成唯一的,不存在的绝对路径。
  • 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. 希望这是有道理的。

You can use Popen.communicate API. 您可以使用Popen.communicate API。

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

The command 命令

Popen.communicate(input=None, timeout=None)

Interact with process: Send data to stdin. 与流程交互:将数据发送到stdin。 Read data from stdout and stderr, until end-of-file is reached. 从stdout和stderr读取数据,直到达到文件结尾。 Wait for the process to terminate. 等待进程终止。

subprocess.run默认等待进程完成。

Use subprocess.Popen and Popen.wait : 使用subprocess.PopenPopen.wait

process = subprocess.Popen(['D:/Test/run-my-script.sh'],shell=True, executable="/bin/bash")
process.wait()

You could also use check_call() instead of Popen. 您也可以使用check_call()而不是Popen

You can use os.system , like this: 您可以使用os.system ,如下所示:

import bpy
import os
os.system("sh "+os.path.abspath('D:/Test/run-my-script.sh'))
print('Hello')

There are apparently cases when the run command fails. 显然,运行命令失败的情况。 This is my workaround: 这是我的解决方法:

def check_has_finished(pfi, interval=1, timeout=100):
    if os.path.exists(pfi):
        if pfi.endswith('.nii.gz'):
            mustend = time.time() + timeout
            while time.time() < mustend:
                try:
                    # Command is an ad hoc one to check if the process  has finished.
                    subprocess.check_output('command {}'.format(pfi), shell=True)
                except subprocess.CalledProcessError:
                    print "Caught CalledProcessError"
                else:
                    return True
                time.sleep(interval)
            msg = 'command {0} not working after {1} tests. \n'.format(pfi, timeout)
            raise IOError(msg)
        else:
            return True
    else:
        msg = '{} does not exist!'.format(pfi)
        raise IOError(msg)

A wild try, but are you running the shell as Admin while Blender as regular user or vice versa? 一个疯狂的尝试,但你是作为管理员运行shell而Blender作为普通用户,反之亦然?

Long story short (very short), Windows UAC is a sort of isolated environment between admin and regular user, so random quirks like this can happen. 长话短说(很短),Windows UAC是管理员和普通用户之间的一种孤立环境,因此可能会发生这样的随机怪癖。 Unfortunately I can't remember the source of this, the closest I found is this . 不幸的是我不记得这个的来源,我发现最接近的是这个

My problem was the exact opposite of yours, the wait() got stuck in a infinite loop because my python REPL was fired from an admin shell and wasn't able to read the state of the regular user subprocess. 我的问题与你的问题完全相反, wait()陷入无限循环,因为我的python REPL是从一个管理shell发出的,并且无法读取常规用户子进程的状态。 Reverting to normal user shell got it fixed. 恢复正常用户shell修复它。 It's not the first time I'm bit from this UAC snafu. 这不是我第一次来自这个UAC snafu。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM