簡體   English   中英

Python AsyncIO的loop.add_reader()期望什么文件描述符對象?

[英]What File Descriptor object does Python AsyncIO's loop.add_reader() expect?

我試圖了解如何在Python 3.4中使用新的AsyncIO功能,我正在努力使用event_loop.add_reader() 從我發現的有限討論看來,它看起來像是從單獨的進程中讀取標准而不是打開文件的內容。 真的嗎? 如果是這樣,似乎沒有AsyncIO特定的方式來集成標准文件IO,這也是真的嗎?

我一直在玩以下代碼。 以下輸出給出異常PermissionError: [Errno 1] Operation not permittedadd_reader()行觸發的/python3.4/selectors.py self._epoll.register(key.fd, epoll_events)的第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)的行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()

這些函數需要一個文件描述符,即操作系統使用的底層整數,而不是Python的文件對象。 基於文件描述符的文件對象在fileno()方法上返回該描述符,例如:

>>> sys.stderr.fileno()
2

在Unix中,文件描述符可以附加到文件或許多其他東西,包括其他進程。

編輯OP的編輯:

正如Max在評論中所說,你不能在本地文件上使用epoll (asyncio使用epoll )。 是的,那有點奇怪。 但是,您可以在管道上使用它,例如:

import asyncio
import urllib.parse
import sys
import pdb
import os

def fileCallback(*args):
    print("Received: " + sys.stdin.readline())

loop = asyncio.get_event_loop()
task = loop.add_reader(sys.stdin.fileno(), fileCallback)
loop.run_forever()

這將回應你在stdin上寫的內容。

你不能在本地文件上使用add_reader,因為:

  • 使用select / poll / epoll無法完成
  • 這取決於操作系統
  • 由於os的限制,它不能完全異步(linux不支持異步fs元數據讀/寫)

但是,從技術上講,是的,您應該能夠執行異步文件系統的讀/寫,(幾乎)所有系統都具有用於在后台執行i / o的DMA機制。 不,本地i / o並不是真的很快,沒有人會想要它,CPU的速度比磁盤i / o快數百萬倍。

如果您想嘗試異步i / o,請查找aiofile或aiofiles

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM