python中的文件到套接字适配器

时间:2015-07-20 08:09:14

标签: python sockets asynchronous serial-port stdin

我想在Windows上使用asyncio库来读取类似文件的对象(例如sys.stdinserial ports)。

但是,expects readable objects to be sockets上的asyncio

是否可以编写一个适配器类来使用套接字API包装类文件对象,以便我可以使用stdinasyncio的串行端口?

如果是这样,请你举个例子,因为我之前从未使用套接字?

1 个答案:

答案 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