我试图进行非阻塞子进程调用,以便从我的main.py程序运行slave.py脚本。我需要将args从main.py传递给slave.py一旦它(slave.py)首次通过subprocess.call启动,此slave.py运行一段时间然后退出。
main.py
for insert, (list) in enumerate(list, start =1):
sys.args = [list]
subprocess.call(["python", "slave.py", sys.args], shell = True)
{loop through program and do more stuff..}
我的奴隶剧本
slave.py
print sys.args
while True:
{do stuff with args in loop till finished}
time.sleep(30)
目前,slave.py阻止main.py运行其余任务,我只想让slave.py独立于main.py,一旦我将args传递给它。这两个脚本不再需要通信。
我在网上发现了一些关于非阻塞subprocess.call的帖子,但是大多数帖子都集中在需要与slave.py进行通信,而这在某些方面我目前并不需要。谁会知道如何以简单的方式实现这一点......?
答案 0 :(得分:41)
您应该使用subprocess.Popen
代替subprocess.call
。
类似的东西:
subprocess.Popen(["python", "slave.py"] + sys.argv[1:])
运行args描述的命令。 等待命令完成,然后返回returncode属性。
(如果您要使用shell = True
,也不要使用列表传递参数。)
这是一个演示非阻塞suprocess调用的MCVE 1 示例:
import subprocess
import time
p = subprocess.Popen(['sleep', '5'])
while p.poll() is None:
print('Still sleeping')
time.sleep(1)
print('Not sleeping any longer. Exited with returncode %d' % p.returncode)
依赖于python语言的最新更改以允许基于协同例程的并行性的替代方法是:
# python3.5 required but could be modified to work with python3.4.
import asyncio
async def do_subprocess():
print('Subprocess sleeping')
proc = await asyncio.create_subprocess_exec('sleep', '5')
returncode = await proc.wait()
print('Subprocess done sleeping. Return code = %d' % returncode)
async def sleep_report(number):
for i in range(number + 1):
print('Slept for %d seconds' % i)
await asyncio.sleep(1)
loop = asyncio.get_event_loop()
tasks = [
asyncio.ensure_future(do_subprocess()),
asyncio.ensure_future(sleep_report(5)),
]
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
1 使用python2.7&amp ;;在OS-X上测试python3.6
答案 1 :(得分:22)
这里有三个层次的彻底性。
正如mgilson所说,如果你只是将subprocess.call
替换为subprocess.Popen
,保持其他所有内容相同,那么main.py将不会等待slave.py在继续之前完成。这本身就足够了。如果您关心zombie processes闲逛,则应保存从subprocess.Popen
返回的对象,稍后再调用其wait
方法。 (当main.py退出时,僵尸会自动消失,所以如果main.py运行很长时间并且/或者可能会创建许多子进程,这只是一个严重的问题。)最后,如果你不想要一个僵尸但是你也不想决定在哪里做等待(这可能适用于两个进程之后运行很长且不可预测的时间),使用python-daemon库让奴隶与主人解除关联 - - 在这种情况下,您可以继续在主服务器中使用subprocess.call
。
答案 2 :(得分:0)
对于Python 3.8.x
import shlex
import subprocess
cmd = "<full filepath plus arguments of child process>"
cmds = shlex.split(cmd)
p = subprocess.Popen(cmds, start_new_session=True)
这将允许父进程在子进程继续运行时退出。不确定僵尸。
在macOS 10.15.5上的Python 3.8.1上进行了测试