我想在Windows上使用asyncio库来读取类似文件的对象(例如sys.stdin
和serial ports)。
但是,expects readable objects to be sockets上的asyncio
。
是否可以编写一个适配器类来使用套接字API包装类文件对象,以便我可以使用stdin
和asyncio
的串行端口?
如果是这样,请你举个例子,因为我之前从未使用套接字?
答案 0 :(得分:2)
不,也许是。
您不能将类文件对象包装为套接字,反之亦然,并期望它能够正常工作。 asyncio
正在使用系统调用来执行异步魔术,而stdin
从系统的角度来看是stdin
,无论你包装它多少。使用默认SelectorEventLoop
时,它使用select之一的系统调用。在Windows上,它使用select
系统调用,不支持除套接字之外的任何内容。
所以,select
糟透了。还有其他选择吗?是。在Windows上,只有Windows,还有另一个用于执行名为IOCP (I/O Completion Ports)
的异步操作的API。它是"notify-on-completion"
类型多路复用器,而不是基于select
的{{1}}类型多路复用器。 API比对文件执行简单的"notify-when-ready"
调用复杂得多,但幸运的是select
已经某些支持它。
asyncio
在Windows上使用IOCP,理论上它应支持从ProactorEventLoop
读取。我没有Windows机器的访问权限,所以我无法对此进行测试,但请试一试:
stdin
在Windows上运行相当于这个:
# vim: filetype=python3 tabstop=2 expandtab
import asyncio as aio
import os
import sys
if os.name == "nt":
proactor_loop = aio.ProactorEventLoop()
aio.set_event_loop(proactor_loop)
@aio.coroutine
def main(loop):
stdin_reader = aio.StreamReader()
stdin_transport, stdin_protocol = yield from loop.connect_read_pipe(
lambda: aio.StreamReaderProtocol(stdin_reader),
sys.stdin
)
line = yield from stdin_reader.read()
print(line.strip().decode("utf-8"))
stdin_transport.close()
loop = aio.get_event_loop()
loop.run_until_complete(main(loop))
loop.close()
如果这样可行,那么至少可以在Windows上执行异步$ echo blha blha blha | python test.py
blha blha blha
。然后你可以为stdin
甚至串行端口尝试类似的东西。
如果所有其他方法都失败了,您可以通过使用stdout/stderr
协程在线程中包含阻塞调用来模拟异步行为:
loop.run_in_executor