【发布时间】:2015-04-22 14:05:37
【问题描述】:
库接受文件输入的“传统”方式是这样的:
def foo(file_obj):
data = file_obj.read()
# Do other things here
客户端代码负责打开文件,寻找合适的点(如果需要),然后关闭它。如果客户想要给我们一个管道或套接字(或StringIO,就此而言),他们可以这样做并且它只是工作。
但这与 asyncio 不兼容,它需要更像这样的语法:
def foo(file_obj):
data = yield from file_obj.read()
# Do other things here
当然,这种语法只适用于 asyncio 对象;试图将它与传统的文件对象一起使用会造成混乱。反之亦然。
更糟糕的是,在我看来,没有办法将这个 yield from 包装在传统的 .read() 方法中,因为我们需要一直到事件循环,而不仅仅是在读取发生的位置。 gevent 库确实做了类似的事情,但我不知道如何将他们的 greenlet 代码改编成生成器。
如果我正在编写一个处理文件输入的库,我应该如何处理这种情况?我需要两个版本的foo() 函数吗?我有很多这样的功能;复制所有这些是不可扩展的。
我可以告诉我的客户开发人员使用 run_in_executor() 或类似的东西,但这感觉就像是在使用 asyncio 而不是使用它。
【问题讨论】:
-
从普通文件读取不会阻塞;您立即获得文件中可用的所有字节,当它们全部消失时,调用完成。所以,没有必要
yield from- 无论如何你永远不会返回控制事件循环。请参阅here 了解更多信息。 -
@dano:当然可以,但是如果客户端代码传递给我们一个异步套接字呢?
-
如果您的 API 需要能够同时处理
asyncio兼容对象和常规文件对象,您可能需要向foo添加逻辑以检测差异并做正确的事。例如。调用out = file_obj.read(),如果out不是bytes对象,则yield from它。除了在线程中运行之外,没有办法让 FS 读取真正异步。 -
我需要能够处理 asyncio 对象,因为我不想给碰巧正在使用 asyncio 写东西并想要打电话到我的图书馆。
-
你可以去aiofiles library看看。
标签: python python-3.x python-asyncio