如何从 Python 异步调用 shell 脚本?
How to asynchronously call a shell script from Python?
我有一个 shell 脚本,它对传递的字符串进行一些处理,然后将其写入文件。但是我不希望我的函数 foo() 等待它完成操作。如何调用 process(msg)
然后继续执行 {code block 2}
而无需等待 process(msg)
完成执行?
def process(msg):
subprocess.call(['sh', './process.sh', msg])
def foo():
# {code block 1}
process(msg)
# {code block 2}
foo()
将被另一个函数调用,几乎每秒一到两次。
subprocess.call() 和 subprocess.run() 创建一个进程,等待它完成,然后 returns 一个 CompletedProcess 对象。
subprocess.Popen() 创建一个进程并 returns 它。它在以前的功能的幕后使用。然后,您可以等待该过程完成、向其发送消息或进行任何您想对其进行的操作。参数 mos 与 call
或 run
.
完全相同
https://docs.python.org/3/library/subprocess.html
更详细地说,Popen 是使用 os 启动新进程的 python 实现。 os.fork() 是一个较低的层次,它实际上并没有做我们在这里想要做的事情,它会产生另一个 python 解释器的实例,其内存状态与当前解释器相同。如果您想使用较低级别的系统调用,os.spawn
比 os.fork
.
更接近 subprocess.run
subprocess.run
为了验证 Popen 正在做你想要的,这个测试程序将弹出“returncode = None”,然后等待 5 秒,并打印“returncode = 0”
from subprocess import Popen
p = Popen(["sleep", "5"])
print("started the proc") # this will print immediately
p.poll() # this checks if the process is done but does not block
print(f"p returncode = {p.returncode}")
p.wait() # this blocks until the process exits
print(f"p returncode = {p.returncode}")
您需要的是 https://docs.python.org/3/library/os.html#os.fork,即 os.fork()
这样您就可以生成一个比父进程寿命更长的子进程,该子进程稍后可以由 systemd
在 Linux 上声明.我不知道 Windows。
只是为了完整性:Python 的 asyncio 提供了一个高级接口来做这件事:
https://docs.python.org/3.9/library/asyncio-subprocess.html#subprocesses
文档中的示例:
import asyncio
async def run(cmd):
proc = await asyncio.create_subprocess_shell(
cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate()
print(f'[{cmd!r} exited with {proc.returncode}]')
if stdout:
print(f'[stdout]\n{stdout.decode()}')
if stderr:
print(f'[stderr]\n{stderr.decode()}')
asyncio.run(run('ls /zzz'))
我有一个 shell 脚本,它对传递的字符串进行一些处理,然后将其写入文件。但是我不希望我的函数 foo() 等待它完成操作。如何调用 process(msg)
然后继续执行 {code block 2}
而无需等待 process(msg)
完成执行?
def process(msg):
subprocess.call(['sh', './process.sh', msg])
def foo():
# {code block 1}
process(msg)
# {code block 2}
foo()
将被另一个函数调用,几乎每秒一到两次。
subprocess.call() 和 subprocess.run() 创建一个进程,等待它完成,然后 returns 一个 CompletedProcess 对象。
subprocess.Popen() 创建一个进程并 returns 它。它在以前的功能的幕后使用。然后,您可以等待该过程完成、向其发送消息或进行任何您想对其进行的操作。参数 mos 与 call
或 run
.
https://docs.python.org/3/library/subprocess.html
更详细地说,Popen 是使用 os 启动新进程的 python 实现。 os.fork() 是一个较低的层次,它实际上并没有做我们在这里想要做的事情,它会产生另一个 python 解释器的实例,其内存状态与当前解释器相同。如果您想使用较低级别的系统调用,os.spawn
比 os.fork
.
subprocess.run
subprocess.run
为了验证 Popen 正在做你想要的,这个测试程序将弹出“returncode = None”,然后等待 5 秒,并打印“returncode = 0”
from subprocess import Popen
p = Popen(["sleep", "5"])
print("started the proc") # this will print immediately
p.poll() # this checks if the process is done but does not block
print(f"p returncode = {p.returncode}")
p.wait() # this blocks until the process exits
print(f"p returncode = {p.returncode}")
您需要的是 https://docs.python.org/3/library/os.html#os.fork,即 os.fork()
这样您就可以生成一个比父进程寿命更长的子进程,该子进程稍后可以由 systemd
在 Linux 上声明.我不知道 Windows。
只是为了完整性:Python 的 asyncio 提供了一个高级接口来做这件事: https://docs.python.org/3.9/library/asyncio-subprocess.html#subprocesses
文档中的示例:
import asyncio
async def run(cmd):
proc = await asyncio.create_subprocess_shell(
cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate()
print(f'[{cmd!r} exited with {proc.returncode}]')
if stdout:
print(f'[stdout]\n{stdout.decode()}')
if stderr:
print(f'[stderr]\n{stderr.decode()}')
asyncio.run(run('ls /zzz'))