为此,您需要一个函数,该函数将采用两个异步序列并将其 合并 ,并在它们可用时从一个或另一个生成结果。有了这样的功能,
run可能看起来像这样:
async def run(cmd): p = await asyncio.create_subprocess_shell(cmd, stdout=PIPE, stderr=PIPE) async for f in merge(p.stdout, p.stderr): print(datetime.now(), f.depre().strip())
merge标准库中尚不存在像这样的函数,但是
aiostream外部库提供了一个。您还可以使用异步生成器和编写自己的代码
asyncio.wait():
async def merge(*iterables): iter_next = {it.__aiter__(): None for it in iterables} while iter_next: for it, it_next in iter_next.items(): if it_next is None: fut = asyncio.ensure_future(it.__anext__()) fut._orig_iter = it iter_next[it] = fut done, _ = await asyncio.wait(iter_next.values(), return_when=asyncio.FIRST_COMPLETED) for fut in done: iter_next[fut._orig_iter] = None try: ret = fut.result() except StopAsyncIteration: del iter_next[fut._orig_iter] continue yield ret
上面的
run内容仍然在细节上与您期望的输出有所不同:不会区分输出行和错误行。但这可以通过使用指示器装饰线条来轻松实现:
async def decorate_with(it, prefix): async for item in it: yield prefix, itemasync def run(cmd): p = await asyncio.create_subprocess_shell(cmd, stdout=PIPE, stderr=PIPE) async for is_out, line in merge(decorate_with(p.stdout, True), decorate_with(p.stderr, False)): if is_out: print(datetime.now(), line.depre().strip()) else: print(datetime.now(), "E:", line.depre().strip())
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)