[英]Can I write to and read from a process in the same asyncio loop?
I have a process that reads input and writes output, like this doubler :我有一个读取输入和写入输出的进程,就像这个doubler :
(in reality it's actually a black box and the input and the output are completely independent) (实际上它实际上是一个黑匣子,输入和输出完全独立)
#!/bin/bash
while read -r i; do
sleep 0.$RANDOM
echo $((i*2))
done
and a few functions in my Python code that feeds this process asynchronously:以及我的 Python 代码中的一些异步提供此过程的函数:
import asyncio
import subprocess
import random
class Feeder:
def __init__(self):
self.process = subprocess.Popen(['doubler.sh'],
stdin=subprocess.PIPE)
def feed(self, value):
self.process.stdin.write(str(value).encode() + b'\n')
self.process.stdin.flush()
feeder = Feeder()
async def feed_random():
while True:
feeder.feed(random.randint(0, 100))
await asyncio.sleep(1)
async def feed_tens():
while True:
feeder.feed(10)
await asyncio.sleep(3.14)
async def main():
await asyncio.gather(
feed_random(),
feed_tens(),
)
if __name__ == '__main__':
asyncio.run(main())
This works well.这很好用。 But I would like to read the output of the process too, like this:
但我也想阅读该过程的输出,如下所示:
...
stdout=subprocess.PIPE
...
for line in feeder.process.stdout:
print("The answer is " + line.decode())
but that is blocking, so the feeding won't happen.但那是阻塞的,所以喂食不会发生。 Can this be done in the same asyncio loop?
这可以在同一个异步循环中完成吗? Or do I need another thread?
还是我需要另一个线程?
Something like this should work.像这样的事情应该有效。 In order to read from
stdout
asynchronously you have to switch to asyncio.subprocess
.为了异步读取
stdout
您必须切换到asyncio.subprocess
。
import asyncio
import random
class Feeder:
def __init__(self):
self.process = None
async def start_process(self):
self.process = await asyncio.create_subprocess_exec('./doubler.sh',
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE)
async def feed(self, value):
self.process.stdin.write(str(value).encode() + b'\n')
await self.process.stdin.drain()
feeder = Feeder()
async def feed_random():
while True:
asyncio.ensure_future(feeder.feed(random.randint(0, 100)))
await asyncio.sleep(1)
async def feed_tens():
while True:
asyncio.ensure_future(feeder.feed(10))
await asyncio.sleep(3.14)
async def read_feed():
while True:
line = await feeder.process.stdout.readline()
print("The answer is " + line.decode('utf-8'))
async def main():
await feeder.start_process()
await asyncio.gather(
feed_random(),
feed_tens(),
read_feed()
)
if __name__ == '__main__':
asyncio.run(main())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.