8

Python 3.4 で新しい AsyncIO 機能を使用する方法を理解しようとしていますが、event_loop.add_reader()の使用方法に苦労しています。私が見つけた限られた議論から、開いているファイルの内容とは対照的に、別のプロセスから標準を読み取るためのように見えます。本当?もしそうなら、標準ファイル IO を統合するための AsyncIO 固有の方法がないように見えますが、これも本当ですか?

私は次のコードで遊んでいます。次の出力は、以下の行によってトリガーされるPermissionError: [Errno 1] Operation not permitted/python3.4/selectors.py の 399 行目からの例外を示します。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)ます。これは基本的に現在の関数を一時停止し、イベント ループ キューに戻して、他のすべての準備完了関数が実行された後に呼び出されるようにします。関数は、スケジュールされた方法に基づいて準備ができていると判断されます。

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()
4

2 に答える 2

10

これらの関数は、Python のファイル オブジェクトではなく、オペレーティング システムが使用する基本的な整数であるファイル記述子を想定しています。ファイル記述子に基づくファイル オブジェクトは、fileno()メソッドでその記述子を返します。たとえば、次のようになります。

>>> sys.stderr.fileno()
2

Unix では、ファイル記述子をファイルや他のプロセスを含む多くのものに添付できます。

OPの編集用に編集:

コメントの Max が言うように、epollローカル ファイル (および asyncio uses 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 に書いたものをエコーし​​ます。

于 2014-08-17T17:59:41.050 に答える