非阻塞subprocess.call

Dav*_*dJB 42 python subprocess

我正在尝试进行非阻塞子进程调用,以便从我的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..}
Run Code Online (Sandbox Code Playgroud)

还有我的奴隶剧本

slave.py
print sys.args
while True:
    {do stuff with args in loop till finished}
    time.sleep(30)
Run Code Online (Sandbox Code Playgroud)

目前,slave.py阻止main.py运行其余的任务,我只想让slave.py独立于main.py,一旦我将args传递给它.这两个脚本不再需要通信.

我在网上发现了一些关于非阻塞subprocess.call的帖子,但是大多数帖子都集中在需要与slave.py进行通信,而这在某些方面我目前并不需要.谁会知道如何以简单的方式实现这一点......?

mgi*_*son 42

你应该使用subprocess.Popen而不是subprocess.call.

就像是:

subprocess.Popen(["python", "slave.py"] + sys.argv[1:])
Run Code Online (Sandbox Code Playgroud)

来自以下文档subprocess.call:

运行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)
Run Code Online (Sandbox Code Playgroud)

依赖于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()
Run Code Online (Sandbox Code Playgroud)

1使用python2.7和python3.6在OS-X上测试

  • 谢谢,这似乎工作,但是当我在slave.py中包含一个While循环时,它似乎卡住了,并没有在循环中执行任何操作(即使使用timer.sleep()函数..? (3认同)

zwo*_*wol 22

这里有三个层次的彻底性.

作为mgilson说,如果你只是换出subprocess.callsubprocess.Popen,保持一切不变,那么main.py不会等待slave.py完成后再继续.这本身就足够了.如果你关心僵尸进程,你应该保存返回的对象subprocess.Popen,稍后再调用它的wait方法.(当main.py退出时,僵尸会自动消失,所以这只是一个严重的问题,如果main.py运行很长时间和/或可能会创建许多子进程.)最后,如果你不想要一个僵尸但是你也不想决定在哪里做等待(这可能适用于两个进程之后运行很长且不可预测的时间),使用python-daemon库让奴隶与master取消关联 - 在那种情况下你可以继续subprocess.call在主人中使用.


JS.*_*JS. 5

对于 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)
Run Code Online (Sandbox Code Playgroud)

这将允许父进程退出,而子进程继续运行。不确定僵尸。

在 macOS 10.15.5 上的 Python 3.8.1 上测试