io — strumienie wejścia/wyjścia¶
Ten moduł zawiera dodatkowe typy obiektów stream (przypominających pliki) oraz funkcje pomocnicze. Udostępnia wbudowaną funkcję open(), a także tekstowe i binarne bufory w pamięci (StringIO, BytesIO), które implementują standardowy interfejs strumieni read/write/seek.
Hierarchia pojęciowa¶
Różnica względem CPythona
Hierarchia pojęciowa bazowych klas strumieni jest w MicroPython uproszczona, co opisano w tej sekcji.
(Abstrakcyjne) bazowe klasy strumieni, które stanowią fundament zachowania wszystkich klas konkretnych, w CPythonie podlegają kilku dychotomiom (klasyfikacjom parami). W MicroPython są one nieco uproszczone i ukryte, aby osiągnąć wyższą wydajność i oszczędzać zasoby.
Ważną dychotomią w CPythonie jest podział na strumienie buforowane i niebuforowane. W MicroPython wszystkie strumienie są obecnie niebuforowane. Wynika to z faktu, że wszystkie nowoczesne systemy operacyjne, a nawet wiele systemów RTOS i sterowników systemów plików, już wykonują buforowanie po swojej stronie. Dodawanie kolejnej warstwy buforowania jest nieproduktywne (problem znany jako „bufferbloat”) i zajmuje cenną pamięć. Należy zauważyć, że nadal istnieją przypadki, w których buforowanie może być przydatne, dlatego w przyszłości możemy wprowadzić opcjonalne wsparcie dla buforowania.
Jednak w CPythonie kolejna ważna dychotomia jest powiązana z „buforowaniem” - chodzi o to, czy strumień może powodować krótkie odczyty/zapisy, czy nie. Krótki odczyt ma miejsce, gdy użytkownik prosi np. o 10 bajtów ze strumienia, ale otrzymuje mniej; podobnie dla zapisów. W CPythonie strumienie niebuforowane są automatycznie podatne na krótkie operacje, natomiast buforowane są przed nimi chronione. Brak krótkich odczytów/zapisów jest ważną cechą, ponieważ pozwala tworzyć bardziej zwięzłe i wydajne programy - coś, co jest wysoce pożądane w MicroPython. Dlatego, choć MicroPython nie obsługuje strumieni buforowanych, nadal zapewnia strumienie bez krótkich operacji. To, czy wystąpią krótkie operacje, czy nie, zależy od potrzeb każdej konkretnej klasy, ale deweloperom zdecydowanie zaleca się preferowanie zachowania bez krótkich operacji z podanych wyżej powodów. Na przykład gniazda sieciowe MicroPython mają gwarancję unikania krótkich odczytów/zapisów. W rzeczywistości obecnie nie ma w rdzeniu przykładu klasy strumienia z krótkimi operacjami, a taka klasa byłaby specyficzna dla konkretnego sprzętu.
Zachowanie bez krótkich operacji staje się trudne w przypadku strumieni nieblokujących, przy czym zachowanie blokujące vs nieblokujące to kolejna dychotomia CPythona, w pełni obsługiwana przez MicroPython. Strumienie nieblokujące nigdy nie czekają na nadejście lub zapisanie danych - odczytują/zapisują tyle, ile to możliwe, lub sygnalizują brak danych (albo brak możliwości zapisu danych). Wyraźnie koliduje to z polityką „braku krótkich operacji” i rzeczywiście przypadek nieblokujących, buforowanych (a więc bez krótkich operacji) strumieni jest w CPythonie zawiły - w niektórych miejscach taka kombinacja jest zabroniona, w niektórych niezdefiniowana lub po prostu nieudokumentowana, a w niektórych przypadkach zgłasza rozwlekłe wyjątki. Sprawa jest znacznie prostsza w MicroPython: strumienie nieblokujące są ważne dla wydajnych operacji asynchronicznych, więc ta właściwość przeważa nad „brakiem krótkich operacji”. Dlatego, choć strumienie blokujące będą unikać krótkich odczytów/zapisów, kiedy tylko to możliwe (jedynym przypadkiem otrzymania krótkiego odczytu jest osiągnięcie końca pliku lub wystąpienie błędu (ale błędy nie zwracają krótkich danych, lecz zgłaszają wyjątki)), strumienie nieblokujące mogą zwracać krótkie dane, aby uniknąć zablokowania operacji.
Ostatnia dychotomia to strumienie binarne vs tekstowe. MicroPython oczywiście je obsługuje, ale o ile w CPythonie strumienie tekstowe są z natury buforowane, o tyle w MicroPython tak nie jest. (Rzeczywiście, to jeden z przypadków, dla których możemy wprowadzić wsparcie dla buforowania.)
Należy zauważyć, że ze względu na wydajność MicroPython nie udostępnia abstrakcyjnych klas bazowych odpowiadających powyższej hierarchii i nie jest możliwe zaimplementowanie ani odziedziczenie klasy strumienia w czystym Pythonie.
Funkcje¶
Klasy¶
- class io.IOBase¶
Klasa bazowa dla obiektów strumieni („przypominających pliki”). Konkretne podklasy implementują niskopoziomowe metody we/wy opisane poniżej (
readinto,write,ioctl); środowisko uruchomieniowe buduje na ich podstawie wyższy poziom protokołu strumienia (read,readline,readlines,close, iterację), dzięki czemu każda instancja strumienia obsługuje te metody nawet wtedy, gdy podklasa ich nie definiuje.Metody implementacyjne (przesłoń je w podklasie):
- readinto(buf: bytearray) int | None¶
Odczytuje bajty do zapisywalnego bufora buf. Zwraca liczbę odczytanych bajtów,
0na końcu strumienia lubNone, jeśli żadne dane nie są obecnie dostępne (dla strumienia nieblokującego).
- write(buf: bytes) int | None¶
Zapisuje bajty z buf. Zwraca liczbę zapisanych bajtów lub
None, jeśli zapis nie może zostać teraz wykonany (dla strumienia nieblokującego).
- ioctl(request: int, arg: int) int¶
Steruje bazowym strumieniem/urządzeniem. request to jeden z kodów żądań
MP_STREAM_*. Zwraca wartość nieujemną w przypadku powodzenia lub ujemną wartośćerrnow przypadku błędu.
Metody protokołu strumienia (dostępne w każdej instancji strumienia):
- read(size: int = -1)¶
Odczytuje i zwraca do size bajtów (lub znaków, w trybie tekstowym). Jeśli size jest pominięte lub ujemne, odczytuje do końca strumienia. Zwraca
bytesdla strumieni binarnych istrdla strumieni tekstowych; pusty wynik oznacza koniec strumienia.
- readline(size: int = -1)¶
Odczytuje i zwraca jeden wiersz, włącznie z końcowym znakiem nowej linii, jeśli jest obecny. Jeśli podano size, odczytywanych jest co najwyżej size bajtów (lub znaków). Zwraca pusty
bytes/strna końcu strumienia.
- readlines() list¶
Odczytuje do końca strumienia i zwraca
listwierszy, każdy z końcowym znakiem nowej linii.
- close() None¶
Zamyka strumień i zwalnia wszelkie bazowe zasoby. Operacje na zamkniętym strumieniu zgłaszają
OSError(lubValueErrordla strumieni w pamięci).
- seek(offset: int, whence: int = 0) int¶
Zmienia bieżącą pozycję w strumieniu na offset bajtów względem whence (
0= początek strumienia,1= bieżąca pozycja,2= koniec strumienia). Zwraca nową pozycję bezwzględną. ZgłaszaOSErrorw przypadku strumienia, w którym nie można przemieszczać pozycji.
- flush() None¶
Opróżnia wszelkie bufory zapisu, przesyłając oczekujące dane do bazowego urządzenia lub pliku. Brak operacji w przypadku strumieni, które nie buforują.
Bezpośrednia iteracja strumienia zwraca jeden wiersz na iterację – równoważne wywoływaniu
readline()w pętli aż do zwrócenia wartownika końca strumienia w postaci pustego wiersza. Strumień obsługuje również protokół menedżera kontekstu, więcwith open(...) as f:automatycznie zamyka strumień.Informacja
Moduł strumieni MicroPython udostępnia także funkcje pomocnicze w języku C z przyrostkiem „1”:
mp_stream_read1_obj,mp_stream_readinto1_objimp_stream_write1_obj, które wykonują pojedyncze bazowe wywołanie we/wy zamiast pętli aż do pełnego spełnienia żądania. Są one używane wewnętrznie przez klasy takie jakmachine.UARTdo implementacji własnychread/write– ale żadna standardowa klasa strumienia nie wiąże ich jako wywoływalnych z Pythona metodread1/readinto1/write1.
- class io.StringIO(string: str = '')¶
Obiekt w pamięci przypominający plik, do wejścia/wyjścia w trybie tekstowym (podobny do zwykłego pliku otwartego z modyfikatorem „t”). Początkową zawartość można podać za pomocą parametru string (który powinien być zwykłym łańcuchem znaków). Instancje obsługują również protokół menedżera kontekstu (można ich używać w instrukcji
with).- read(size: int = -1) str¶
Odczytuje i zwraca do size znaków. Jeśli size jest pominięte lub ujemne, odczytuje i zwraca całą pozostałą zawartość.
- readline(size: int = -1) str¶
Odczytuje i zwraca jeden wiersz. Jeśli podano size, odczytywanych jest co najwyżej size znaków.
- readinto(buf: bytearray) int¶
Odczytuje do wstępnie zaalokowanego, zapisywalnego bufora buf i zwraca liczbę odczytanych bajtów.
- seek(offset: int, whence: int = 0) int¶
Zmienia pozycję w strumieniu na offset względem whence (
0= początek,1= bieżąca,2= koniec) i zwraca nową pozycję bezwzględną.
- close() None¶
Zamyka strumień i zwalnia bazowy bufor. Dalsze operacje na zamkniętym strumieniu zgłaszają
ValueError.
- class io.StringIO(alloc_size: int)
Tworzy pusty obiekt
StringIOz wstępną alokacją na co najwyżej alloc_size bajtów, dzięki czemu zapisanie do tylu bajtów nie spowoduje ponownej alokacji bufora (unikając sytuacji braku pamięci lub fragmentacji pamięci). Ten konstruktor jest rozszerzeniem MicroPython zalecanym tylko w szczególnych przypadkach i dla bibliotek systemowych, a nie dla aplikacji użytkownika końcowego.Różnica względem CPythona
Ten konstruktor jest rozszerzeniem MicroPython.
- read(size: int = -1) str
Odczytuje i zwraca do size znaków. Jeśli size jest pominięte lub ujemne, odczytuje i zwraca całą pozostałą zawartość.
- readline(size: int = -1) str
Odczytuje i zwraca jeden wiersz. Jeśli podano size, odczytywanych jest co najwyżej size znaków.
- readinto(buf: bytearray) int
Odczytuje do wstępnie zaalokowanego, zapisywalnego bufora buf i zwraca liczbę odczytanych bajtów.
- seek(offset: int, whence: int = 0) int
Zmienia pozycję w strumieniu na offset względem whence (
0= początek,1= bieżąca,2= koniec) i zwraca nową pozycję bezwzględną.
- tell() int
Zwraca bieżącą pozycję w strumieniu.
- flush() None
Opróżnia bufory zapisu. Dla strumienia w pamięci jest to operacja pusta.
- close() None
Zamyka strumień i zwalnia bazowy bufor. Dalsze operacje na zamkniętym strumieniu zgłaszają
ValueError.
- getvalue() str
Zwraca bieżącą zawartość bazowego bufora.
- class io.BytesIO(string: bytes = b'')¶
Obiekt w pamięci przypominający plik, do wejścia/wyjścia w trybie binarnym (podobny do zwykłego pliku otwartego z modyfikatorem „b”). Początkową zawartość można podać za pomocą parametru string (który powinien być obiektem bytes). Instancje obsługują również protokół menedżera kontekstu (można ich używać w instrukcji
with).- read(size: int = -1) bytes¶
Odczytuje i zwraca do size bajtów. Jeśli size jest pominięte lub ujemne, odczytuje i zwraca całą pozostałą zawartość.
- readline(size: int = -1) bytes¶
Odczytuje i zwraca jeden wiersz. Jeśli podano size, odczytywanych jest co najwyżej size bajtów.
- readinto(buf: bytearray) int¶
Odczytuje do wstępnie zaalokowanego, zapisywalnego bufora buf i zwraca liczbę odczytanych bajtów.
- seek(offset: int, whence: int = 0) int¶
Zmienia pozycję w strumieniu na offset względem whence (
0= początek,1= bieżąca,2= koniec) i zwraca nową pozycję bezwzględną.
- close() None¶
Zamyka strumień i zwalnia bazowy bufor. Dalsze operacje na zamkniętym strumieniu zgłaszają
ValueError.
- class io.BytesIO(alloc_size: int)
Tworzy pusty obiekt
BytesIOz wstępną alokacją na co najwyżej alloc_size bajtów, dzięki czemu zapisanie do tylu bajtów nie spowoduje ponownej alokacji bufora (unikając sytuacji braku pamięci lub fragmentacji pamięci). Ten konstruktor jest rozszerzeniem MicroPython zalecanym tylko w szczególnych przypadkach i dla bibliotek systemowych, a nie dla aplikacji użytkownika końcowego.Różnica względem CPythona
Ten konstruktor jest rozszerzeniem MicroPython.
- read(size: int = -1) bytes
Odczytuje i zwraca do size bajtów. Jeśli size jest pominięte lub ujemne, odczytuje i zwraca całą pozostałą zawartość.
- readline(size: int = -1) bytes
Odczytuje i zwraca jeden wiersz. Jeśli podano size, odczytywanych jest co najwyżej size bajtów.
- readinto(buf: bytearray) int
Odczytuje do wstępnie zaalokowanego, zapisywalnego bufora buf i zwraca liczbę odczytanych bajtów.
- seek(offset: int, whence: int = 0) int
Zmienia pozycję w strumieniu na offset względem whence (
0= początek,1= bieżąca,2= koniec) i zwraca nową pozycję bezwzględną.
- tell() int
Zwraca bieżącą pozycję w strumieniu.
- flush() None
Opróżnia bufory zapisu. Dla strumienia w pamięci jest to operacja pusta.
- close() None
Zamyka strumień i zwalnia bazowy bufor. Dalsze operacje na zamkniętym strumieniu zgłaszają
ValueError.
- getvalue() bytes
Zwraca bieżącą zawartość bazowego bufora.