【发布时间】:2014-08-17 17:55:11
【问题描述】:
我正在尝试了解如何在 Python 3.4 中使用新的 AsyncIO 功能,但我正在努力解决如何使用 event_loop.add_reader() 的问题。从limited discussions 我发现它看起来像是从一个单独的进程中读取标准而不是打开文件的内容。真的吗?如果是这样,似乎没有 AsyncIO 特定的方式来集成标准文件 IO,这也是真的吗?
我一直在玩下面的代码。下面的输出给出了 /python3.4/selectors.py self._epoll.register(key.fd, epoll_events) 的第 399 行中的 PermissionError: [Errno 1] Operation not permitted 异常,该异常由下面的 add_reader() 行触发
import asyncio
import urllib.parse
import sys
import pdb
import os
def fileCallback(*args):
pdb.set_trace()
path = sys.argv[1]
loop = asyncio.get_event_loop()
#fd = os.open(path, os.O_RDONLY)
fd = open(path, 'r')
#data = fd.read()
#print(data)
#fd.close()
pdb.set_trace()
task = loop.add_reader(fd, fileCallback, fd)
loop.run_until_complete(task)
loop.close()
编辑
对于那些正在寻找如何使用 AsyncIO 一次读取多个文件的示例的人,我很好奇,这里有一个如何实现的示例。秘密在yield from asyncio.sleep(0) 行中。这实质上会暂停当前函数,将其放回事件循环队列中,以便在所有其他就绪函数执行后调用。函数根据它们的调度方式确定是否准备就绪。
import asyncio
@asyncio.coroutine
def read_section(file, length):
yield from asyncio.sleep(0)
return file.read(length)
@asyncio.coroutine
def read_file(path):
fd = open(path, 'r')
retVal = []
cnt = 0
while True:
cnt = cnt + 1
data = yield from read_section(fd, 102400)
print(path + ': ' + str(cnt) + ' - ' + str(len(data)))
if len(data) == 0:
break;
fd.close()
paths = ["loadme.txt", "loadme also.txt"]
loop = asyncio.get_event_loop()
tasks = []
for path in paths:
tasks.append(asyncio.async(read_file(path)))
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
【问题讨论】:
-
请参阅this question 了解失败的原因;
epoll不支持常规文件。 -
@dano:如果我在 FreeBSD 上这样做,它会使用 kqueue 并处理常规文件吗?
-
我不确定,但我知道 AsyncIO 的目的是公开文件系统的标准 IO 回调。因此,如果这是 FreeBSD 执行 IO 回调的标准方式,那么可能
-
@JanusTroelsen 在 FreeBSD 上使用
SelectorEventLoop,它使用selectors模块为平台选择最有效的事件循环。如果那是 kqueue,那么这应该是selectors选择的。不过,我不知道这是否会使add_reader与常规文件一起使用。如果你试一试,请告诉我进展如何!
标签: python file-io python-3.4 python-asyncio