10.5.12.3 向子进程发送数据
前面的两个例子只使用了一个通信通道从第二个进程读取数据。通常有必要把数据发送给一个命令来处理。下面的例子定义了一个协程来执行UNIX命令tr,转换其输入流中的字符。在这里,tr用来把小写字母转换为大写字母。
to_upper()协程接收一个事件循环和一个输入串作为参数。它会创建另一个进程运行"tr [:lower:] [:upper:]"。
import asyncio
import asyncio.subprocess
async def to_upper(input):
print('in to_upper')
create = asyncio.create_subprocess_exec(
'tr','[:lower:]','[:upper:]',
stdout=asyncio.subprocess.PIPE,
stdin=asyncio.subprocess.PIPE,
)
print('launching process')
proc = await create
print('pid {}'.format(proc.pid))
# 接下来,to_upper()使用Process的communicate()方法将输入串发送到这个命令,并异步
# 地读取得到的所有输出。与subprocess.Popen中的相应方法一样,communicate()会返回
# 这个方法输出的所有字节串。如果一个命令有可能生成太多的数据(在内存中放不下),
# 那么不能一次生成全部输入,或者必须增量地处理输出,一种更好的方法是直接使用
# Process的stdin,stdout和stderr句柄而不是调用communicate()。
print('communicating with process')
stdout,stderr = await proc.communicate(input.encode())
# I/O完成后,要等待进程完全退出,确保他得到适当的清理。
print('waiting for process tp complete')
await proc.wait()
# 然后可以检查返回码,并解码输出字节串以准备协程的返回值。
return_code = proc.returncode
print('return_code {}'.format(return_code))
if not return_code:
results = bytes(stdout).decode()
else:
results = ''
return (return_code,results)
# 程序的主要比分建立了一个要转换的消息中,并建立事件循环来运行to_upper(),然后
# 输出结果。
MESSAGE = """
THis message will be converted
to all caps.
"""
event_loop = asyncio.get_event_loop()
try:
return_code,results = event_loop.run_until_complete(
to_upper(MESSAGE)
)
finally:
event_loop.close()
if return_code:
print('error exit {}'.format(return_code))
else:
print('Original:{!r}'.format(MESSAGE))
print('Changed :{!r}'.format(results))
输出显示了操作序列以及这个简单文本消息的转换结果。