简体   繁体   English

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

[英]File to socket adapter in python

I want to use the asyncio library on Windows to read file-like objects (such as sys.stdin and serial ports ). 我想在Windows上使用asyncio库来读取类似文件的对象(例如sys.stdinserial ports )。

However, asyncio on Windows expects readable objects to be sockets . 但是,Windows上的asyncio 期望可读对象为sockets

Is it possible to write an adapter class to wrap a file-like object with the API of a socket so that I could use stdin and serial ports with asyncio ? 是否可以编写一个适配器类来使用套接字的API包装类似文件的对象,以便我可以将stdin和串行端口与asyncio一起asyncio

If so, please could you give an example because I've never used sockets before? 如果是这样,请给我一个例子,因为我以前从未使用过套接字吗?

Short answer 简短答案

No and maybe yes. 不,也许是。

Long answer 长答案

You can't just wrap a file-like object as a socket, or vice-versa, and expect it to work. 您不能只是将类似文件的对象包装为套接字,反之亦然,并且期望它能工作。 asyncio is using system calls under the hood to do its async magic and stdin is stdin from the system's point of view no mater how much you wrap it. asyncio使用系统调用来执行其异步魔术,从系统的角度来看, stdinstdin ,无论包装多少。 When using the default SelectorEventLoop it uses one of the select -like system calls. 使用默认的SelectorEventLoop它会使用类似select的系统调用之一。 On Windows it uses the select system call, which does not support anything but sockets. 在Windows上它使用select系统调用,它支持什么,但插座。

So, select sucks on windows. 因此, select在窗口上烂透了。 Is there another option? 还有其他选择吗? Yes. 是。 On Windows, and only Windows, there is another API for doing async operations called IOCP (I/O Completion Ports) . 在Windows(仅Windows)上,还有另一个API用于执行异步操作,称为IOCP (I/O Completion Ports) It's a "notify-on-completion" type multiplexer as opposed to the select based "notify-when-ready" type multiplexers. 它是"notify-on-completion"类型的多路复用器,而不是基于select"notify-when-ready"类型的多路复用器。 The API is much more complicated than doing a simple select call on a file, but fortunately asyncio has some support for it already. 该API比对文件进行简单的select调用要复杂得多,但是幸运的是asyncio已经对此文件提供了一些支持。

The ProactorEventLoop uses IOCP on Windows and it should theoretically supports reading from stdin . ProactorEventLoop在Windows上使用IOCP,并且理论上应该支持从stdin读取。 I don't have access to a Windows machine so I can't test this, but give this a go: 我无权使用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()

And run the equivalent of this on Windows: 并在Windows上运行等效的命令:

$ echo blha blha blha | python test.py
blha blha blha

If this works, then at least you can do async stdin on Windows. 如果可行,那么至少您可以在Windows上执行异步stdin And then you could try something similar for stdout/stderr or perhaps even serial ports. 然后您可以为stdout/stderr甚至串行端口尝试类似的操作。

If all else fails, you could always simulate async behaviour by wrapping blocking calls in threads using the loop.run_in_executor coroutine: 如果所有其他方法均失败,则始终可以通过使用loop.run_in_executor协程将阻塞调用包装在线程中来模拟异步行为:

yield from loop.run_in_executor(None, sys.stdin.readline)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM