【发布时间】:2021-07-02 10:45:30
【问题描述】:
我有 3 个脚本需要组合才能处理管道中的数据。脚本永远运行,直到执行被用户中断。这是它们在终端中的执行方式:
script1_producer.sh | script2_processor.sh | script3_processor.sh
script1_producer.sh 生成要处理的数据(例如,它只打印递增的数字)
i=1
while true; do
echo $i
i=$(($i+1))
sleep 1
done
script2_processor.sh 使用来自 Script1 的数据并计算新的数据流(每个数字相乘*2):
while read -r line
do
echo "$(($line*2))"
done < "${1:-/dev/stdin}"
script3_processor.sh 使用来自 Script2 的数据并计算一个新的数据流(给每个数字添加一个字母):
while read -r line
do
echo "A$(($line))"
done < "${1:-/dev/stdin}"
运行script1_producer.sh | script2_processor.sh | script3_processor.sh时的结果输出:
A2
A4
A6
...
现在我希望这些脚本由 Python 子进程使用管道控制。
最后,我需要处理script3_processor.sh 的输出并对每一行执行操作。
我正在尝试使用 asyncio 来实现这一点,但如果可能的话,不使用 asyncio 是可以的。
这是我的 - 非常天真的尝试process_pipes.py:
import asyncio
import subprocess
import os
async def async_receive():
p1 = await asyncio.create_subprocess_exec(
"./script1_producer.sh",
stdout=subprocess.PIPE,
)
p2 = await asyncio.create_subprocess_exec(
"./script2_processor.sh",
stdin=p1.stdout,
stdout=subprocess.PIPE,
)
p3 = await asyncio.create_subprocess_exec(
"./script3_processor.sh",
stdin=p2.stdout,
stdout=subprocess.PIPE,
)
# Read just one line to test
data = await p3.stdout.readline()
print(data)
asyncio.run(async_receive())
不幸的是,执行此脚本时出现以下异常:
Traceback (most recent call last):
File "process_pipes.py", line 28, in <module>
asyncio.run(async_receive())
File "/usr/lib/python3.8/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
return future.result()
File "process_pipes.py", line 12, in async_receive
p2 = await asyncio.create_subprocess_exec(
File "/usr/lib/python3.8/asyncio/subprocess.py", line 236, in create_subprocess_exec
transport, protocol = await loop.subprocess_exec(
File "/usr/lib/python3.8/asyncio/base_events.py", line 1630, in subprocess_exec
transport = await self._make_subprocess_transport(
File "/usr/lib/python3.8/asyncio/unix_events.py", line 197, in _make_subprocess_transport
transp = _UnixSubprocessTransport(self, protocol, args, shell,
File "/usr/lib/python3.8/asyncio/base_subprocess.py", line 36, in __init__
self._start(args=args, shell=shell, stdin=stdin, stdout=stdout,
File "/usr/lib/python3.8/asyncio/unix_events.py", line 789, in _start
self._proc = subprocess.Popen(
File "/usr/lib/python3.8/subprocess.py", line 808, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File "/usr/lib/python3.8/subprocess.py", line 1477, in _get_handles
p2cread = stdin.fileno()
AttributeError: 'StreamReader' object has no attribute 'fileno'
我在 Stackoverflow 和其他地方阅读了一些示例,告诉我以不同的方式处理管道,但无法让这些在我的场景中发挥作用。
如何模拟运行 script1_producer.sh | script2_processor.sh | script3_processor.sh 并在 Python 中处理 script3 的输出?
【问题讨论】:
标签: python subprocess python-asyncio