Python subprocess.call 不等待进程完成搅拌机
Posted
技术标签:
【中文标题】Python subprocess.call 不等待进程完成搅拌机【英文标题】:Python subprocess.call not waiting for process to finish blender 【发布时间】:2017-09-07 13:18:25 【问题描述】:我在搅拌机中有一个 python 脚本
subprocess.call(os.path.abspath('D:/Test/run-my-script.sh'),shell=True)
随后是许多其他代码,这些代码依赖于这个 shell 脚本来完成。发生了什么是它不等待它完成,我不知道为什么?我什至尝试使用Popen
而不是call
,如图所示:
p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),shell=True)
p1.wait()
我尝试使用 commuincate 但它仍然不起作用:
p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),shell=True).communicate()
此 shell 脚本在 MacOS 上运行良好(更改路径后)并在使用 subprocess.call(['sh', '/userA/Test/run-my-script.sh'])
时等待
但在 Windows 上会发生这种情况,我在 Blender 中运行下面的 python 脚本,然后一旦它到达子进程行 Git bash
打开并运行 shell 脚本,而 Blender 不等待它完成它只是打印Hello
在其控制台中,无需等待 Git Bash 完成。有什么帮助吗?
import bpy
import subprocess
subprocess.call(os.path.abspath('D:/Test/run-my-script.sh'),shell=True)
print('Hello')
【问题讨论】:
当您从命令行运行D:/Test/run-my-script.sh
时,Windows 上会发生什么?它会立即返回吗?
你能发布 bash 脚本吗?
【参考方案1】:
您可以使用subprocess.call
来做到这一点。
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)
运行 args 描述的命令。等待命令完成,然后返回 returncode 属性。
编辑:我想我对正在发生的事情有预感。该命令适用于您的 Mac,因为我相信 Mac 支持开箱即用的 Bash(至少在功能上等效),而在 Windows 上,它会看到您尝试运行“.sh”文件并触发我认为 Git Bash 在启动时会执行几次分叉。
由于这个 Python 认为你的脚本已经完成,PID 就消失了。
如果我是你,我会这样做:
使用tempfile
模块在“启动”脚本中生成唯一的、不存在的绝对路径。
启动脚本时,将刚刚创建的路径作为参数传递。
脚本启动时,让它在路径中创建一个文件。完成后,删除文件。
启动脚本应注意该文件的创建和删除以指示脚本的状态。
希望这是有道理的。
【讨论】:
在某些情况下这不起作用。例如,在我的情况下,该过程是一个创建文件的程序,然后它访问该文件以在一段时间内修改其内容。 subprocess.call 将过程视为已完成,当文件创建时程序仍在修改文件的内容并且过程仍在进行中。有什么解决方法吗? @SeF 然后你做了一些意想不到的事情——文档非常明确地说明了函数是如何工作的。也许您正在分叉或执行另一个进程?【参考方案2】:您可以使用 Popen.communicate API。
p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),shell=True)
sStdout, sStdErr = p1.communicate()
命令
Popen.communicate(input=None, timeout=None)
与进程交互:将数据发送到标准输入。从 stdout 和 stderr 读取数据,直到到达文件结尾。等待进程终止。
【讨论】:
感谢所有参与赏金的人,这个答案提出了一个替代等待命令的方法,它似乎并不总是有效。【参考方案3】:subprocess.run
默认会等待进程完成。
【讨论】:
你的问题给我的印象是你使用的是subprocess.Popen
而不是subprocess.run
使用run 时它不等待吗?
我使用了 subprocess.run 也没有等待
如果您使用os.spawn
方法之一并将os.P_WAIT
作为第一个参数会发生什么?
“作为第一个参数”是什么意思?
第一个参数。在您尝试调用的命令的参数之前。这是启动进程并告诉 python 等待它完成的旧方法。例如os.spawn(os.P_WAIT, "run_my_script.sh")
【参考方案4】:
使用 subprocess.Popen 和 Popen.wait:
process = subprocess.Popen(['D:/Test/run-my-script.sh'],shell=True, executable="/bin/bash")
process.wait()
您也可以使用check_call() 代替 Popen。
【讨论】:
【参考方案5】:你可以使用os.system
,像这样:
import bpy
import os
os.system("sh "+os.path.abspath('D:/Test/run-my-script.sh'))
print('Hello')
【讨论】:
os.system
在某些情况下很好,但并非总是如此。他可能只是在调用他的二进制文件时出错,所以建议使用 os.system 并不重要。【参考方案6】:
显然有一些运行命令失败的情况。 这是我的解决方法:
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)
【讨论】:
【参考方案7】:尝试一下,但是您是以管理员身份运行 shell 而 Blender 以普通用户身份运行,反之亦然?
长话短说(非常短),Windows UAC 是一种介于管理员和普通用户之间的隔离环境,因此可能会发生这种随机的怪癖。不幸的是,我不记得它的来源,我找到的最接近的是this。
我的问题与你的完全相反,wait()
陷入了无限循环,因为我的 python REPL 是从管理 shell 触发的,并且无法读取常规用户子进程的状态。恢复到普通用户 shell 可以修复它。这不是我第一次被 UAC 搞砸了。
【讨论】:
以上是关于Python subprocess.call 不等待进程完成搅拌机的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 python 2.7.6 使 subprocess.call 超时?
在 Python 中使用 subprocess.call 播放音频
Python执行外部命令(subprocess,call,Popen)
Python下的subprocess.call()使用和注意事项