在 asyncio 中调用命令行程序#
Python 编写的应用程序需要 Python 运行环境,然而,并不是所有想要交互的组件都是用 Python 编写的。可能已经使用了 C++ 、Go、Rust 或其他语言编写的应用程序,这些语言提供了更好的运行时特征,或者可以提供很优秀的实现方式,而无需重新实现。可能还希望使用操作系统提供的命令行实用工具,例如 grep 用于搜索大型文件,curl 用于发出 HTTP 请求等。
import asyncio
from asyncio.subprocess import Process
async def main():
process: Process = await asyncio.create_subprocess_exec("ls", "-l")
print(f"进程的 pid: {process.pid}")
# 等待子进程执行完毕,并返回状态码
status_code = await process.wait()
print(f"status code: {status_code}")
await main()
进程的 pid: 3339
total 28
-rw-r--r-- 1 runner docker 8884 Mar 25 07:16 asyncio-queue.ipynb
-rw-r--r-- 1 runner docker 4994 Mar 25 07:16 asyncio-subprocess.ipynb
-rw-r--r-- 1 runner docker 67 Mar 25 07:16 index.md
-rw-r--r-- 1 runner docker 2631 Mar 25 07:16 switch.ipynb
status code: 0
控制标准输出:
import asyncio
from asyncio.subprocess import Process, PIPE
from asyncio.streams import StreamReader
async def main():
process: Process = await asyncio.create_subprocess_exec("ls", "-la", stdout=PIPE)
print(f"进程的 pid: {process.pid}")
await process.wait()
# 当子进程执行完毕时,拿到它的 stdout 属性
stdout: StreamReader = process.stdout
# 读取输出内容,如果子进程没有执行完毕,那么 await stdout.read() 会阻塞
content = (await stdout.read()).decode("utf-8")
print(content[: 100])
await main()
进程的 pid: 3340
total 36
drwxr-xr-x 2 runner docker 4096 Mar 25 07:16 .
drwxr-xr-x 11 runner docker 4096 Mar 25 07:
与进程交互#
from pathlib import Path
temp_dir = Path(".temp")
# 创建临时目录
if not temp_dir.exists():
temp_dir.mkdir(exist_ok=True)
%%file {temp_dir}/write_data.py
import sys
[sys.stdout.buffer.write(b'!Hello there!!\n') for _ in range(1000000)]
sys.stdout.flush()
Writing .temp/write_data.py
from asyncio.subprocess import Process, PIPE
async def main():
process: Process = await asyncio.create_subprocess_exec(
"python", f"{temp_dir}/write_data.py", stdout=PIPE, stderr=PIPE)
print(f"进程的 pid: {process.pid}")
# 同样会阻塞,直到进程完成
stdout, stderr = await process.communicate()
print(f"状态码: {process.returncode}")
await main()
进程的 pid: 3341
状态码: 0