Próbuję zrozumieć, jak korzystać z nowej funkcjonalności asyncio w Pythonie 3.4 i zmagam się z tym, jak korzystać z event_loop.add_reader () <). Z Ograniczone dyskusje, które znalazłem, wygląda na to, że czytanie standardowego Oddzielny proces w przeciwieństwie do zawartości otwartego pliku. Czy to prawda? Jeśli tak, wydaje się, że nie ma asyncio specyficzny sposób, aby zintegrować standardowy plik IO, czy to prawda?
Gram z poniższym kodem. Wyjście poniższych daje wyjątek PermissionError: [Errno 1] Operation not permitted
z linii 399 z /Python3.4/selektors.py self._epoll.register(key.fd, epoll_events)
jest wywołany przez linię add_reader()
poniżej
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()
EDYTUJ
Dla tych, którzy szukają przykładu sposobu korzystania z asyncio do czytania więcej niż jednego pliku na raz, jakbym był ciekawy, oto przykład tego, jak można go osiągnąć. Sekret jest w linii yield from asyncio.sleep(0)
. Zasadniczo zatrzymuje się bieżącą funkcję, umieszczając ją z powrotem w kolejce pętli zdarzeń, do wywołania po wykonaniu wszystkich innych gotowych funkcji. Funkcje są zdecydowane być gotowe na podstawie tego, jak zostały zaplanowane.
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()
2 odpowiedzi
Funkcje te oczekują deskryptora plików, to znaczy, podstawowe liczby całkowite używa systemu operacyjnego, a nie obiekty plików Pythona. Obiekty plików, które są oparte na deskryptach plików zwracają ten deskryptor na metodzie fileno()
, więc na przykład:
>>> sys.stderr.fileno()
2
W UNIX deskrypci plików mogą być dołączone do plików lub wielu innych rzeczy, w tym innych procesów.
Edytuj dla Edycja OP:
Jak mówi Max w komentarzach, nie możesz użyć epoll
w lokalnych plikach (i asyncio używa epoll
). Tak, to jest dziwne. Możesz jednak użyć go na rurach, na przykład:
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()
To będzie echo piszesz na stdin.
Nie można użyć Dodaj_Reader na lokalnych plikach, ponieważ:
- Nie można tego zrobić za pomocą Wybierz / Eld / EPOLL
- Zależy to od systemu operacyjnego
- Nie może być w pełni asynchroniczny ze względu na ograniczenia systemu operacyjnego (Linux nie obsługuje Metadanych ASync FS Read / zapis)
Ale, technicznie, tak, powinieneś być w stanie wykonać Async Read / Write, (prawie) Wszystkie systemy mają mechanizm DMA do robienia I / O "w tle". I nie, lokalny I / O nie jest naprawdę Naprawdę Szybko tak, że nikt nie chciał, że procesor są rzędu milionów razy szybciej, że dysk I / O.
Szukaj aiofile lub aiofiles, jeśli chcesz spróbować async I / O
Podobne pytania
Powiązane pytania
Nowe pytania
python
Python to wielozadaniowy, wielozadaniowy język programowania dynamicznie typowany. Został zaprojektowany tak, aby był szybki do nauczenia się, zrozumienia i użycia oraz wymuszania czystej i jednolitej składni. Należy pamiętać, że Python 2 oficjalnie nie jest obsługiwany od 01-01-2020. Mimo to, w przypadku pytań Pythona specyficznych dla wersji, dodaj znacznik [python-2.7] lub [python-3.x]. Korzystając z wariantu Pythona (np. Jython, PyPy) lub biblioteki (np. Pandas i NumPy), należy umieścić go w tagach.