io — invoer-/uitvoerstromen

Deze module bevat aanvullende typen stream-objecten (bestandachtige objecten) en hulpfuncties. Hij stelt de ingebouwde open() beschikbaar, samen met tekst- en binaire buffers in het geheugen (StringIO, BytesIO) die de standaard read/write/seek-streaminterface implementeren.

Conceptuele hiërarchie

Verschil met CPython

De conceptuele hiërarchie van de basisstreamklassen is in MicroPython vereenvoudigd, zoals in deze sectie beschreven.

(Abstracte) basisstreamklassen, die als fundament dienen voor het gedrag van alle concrete klassen, houden zich in CPython aan enkele dichotomieën (paarsgewijze classificaties). In MicroPython zijn ze enigszins vereenvoudigd en impliciet gemaakt om een hogere efficiëntie te bereiken en bronnen te besparen.

Een belangrijke dichotomie in CPython is gebufferde versus ongebufferde streams. In MicroPython zijn alle streams momenteel ongebufferd. Dit komt doordat alle moderne besturingssystemen, en zelfs veel RTOS’en en bestandssysteemstuurprogramma’s, aan hun kant al buffering uitvoeren. Een extra bufferlaag toevoegen werkt averechts (een probleem dat bekendstaat als “bufferbloat”) en kost kostbaar geheugen. Merk op dat er nog steeds gevallen zijn waarin buffering nuttig kan zijn, dus mogelijk introduceren we later optionele bufferingondersteuning.

Maar in CPython is een andere belangrijke dichotomie gekoppeld aan “bufferedheid” - namelijk of een stream korte read-/write-bewerkingen kan ondervinden of niet. Een korte read is wanneer een gebruiker bijvoorbeeld 10 bytes uit een stream opvraagt, maar minder krijgt; voor writes geldt dit analoog. In CPython zijn ongebufferde streams automatisch vatbaar voor korte bewerkingen, terwijl gebufferde streams hiertegen gegarandeerd beschermd zijn. Het ontbreken van korte read-/write-bewerkingen is een belangrijke eigenschap, omdat het de ontwikkeling van beknoptere en efficiëntere programma’s mogelijk maakt - iets wat voor MicroPython zeer wenselijk is. Dus hoewel MicroPython geen gebufferde streams ondersteunt, biedt het toch streams zonder korte bewerkingen. Of er korte bewerkingen zullen zijn of niet, hangt af van de behoeften van elke specifieke klasse, maar ontwikkelaars wordt ten zeerste aangeraden om de voorkeur te geven aan gedrag zonder korte bewerkingen, om de hierboven genoemde redenen. MicroPython-sockets zijn bijvoorbeeld gegarandeerd vrij van korte read-/write-bewerkingen. Op dit moment is er feitelijk geen voorbeeld van een streamklasse met korte bewerkingen in de kern, en zo’n klasse zou specifiek zijn voor bepaalde hardware.

Het gedrag zonder korte bewerkingen wordt lastig in het geval van niet-blokkerende streams, waarbij blokkerend versus niet-blokkerend gedrag een andere CPython-dichotomie is, die volledig door MicroPython wordt ondersteund. Niet-blokkerende streams wachten nooit tot er gegevens binnenkomen of worden weggeschreven - ze lezen/schrijven wat mogelijk is, of signaleren een gebrek aan gegevens (of het onvermogen om gegevens te schrijven). Dit conflicteert uiteraard met het beleid van “geen korte bewerkingen”, en inderdaad is het geval van niet-blokkerende gebufferde (en dus geen korte bewerkingen) streams in CPython ingewikkeld - op sommige plaatsen is zo’n combinatie verboden, op sommige is het ongedefinieerd of gewoon niet gedocumenteerd, en in sommige gevallen leidt het tot uitvoerige uitzonderingen. De zaak is in MicroPython veel eenvoudiger: niet-blokkerende streams zijn belangrijk voor efficiënte asynchrone bewerkingen, dus deze eigenschap prevaleert boven die van “geen korte bewerkingen”. Dus hoewel blokkerende streams korte read-/write-bewerkingen zoveel mogelijk vermijden (het enige geval waarin een korte read optreedt, is als het einde van het bestand wordt bereikt, of bij een fout (maar fouten geven geen korte gegevens terug, maar werpen uitzonderingen)), kunnen niet-blokkerende streams korte gegevens produceren om de bewerking niet te blokkeren.

De laatste dichotomie is binaire versus tekststreams. MicroPython ondersteunt deze uiteraard, maar terwijl tekststreams in CPython inherent gebufferd zijn, zijn ze dat in MicroPython niet. (Dit is inderdaad een van de gevallen waarvoor we mogelijk bufferingondersteuning introduceren.)

Merk op dat MicroPython omwille van de efficiëntie geen abstracte basisklassen biedt die overeenkomen met de bovenstaande hiërarchie, en dat het niet mogelijk is om een streamklasse in puur Python te implementeren of er een subklasse van te maken.

Functies

io.open(name: str, mode: str = 'r', **kwargs) Any

Open een bestand. De ingebouwde functie open() is een alias voor deze functie. De parameter mode wordt altijd ondersteund; ondersteuning voor andere argumenten kan variëren.

Klassen

class io.IOBase

Basisklasse voor stream-objecten (“bestandachtige” objecten). Concrete subklassen implementeren de onderstaande low-level I/O-methoden (readinto, write, ioctl); de runtime bouwt daarbovenop het hogere streamprotocol (read, readline, readlines, close, iteratie), zodat elke streaminstantie die methoden ondersteunt, zelfs wanneer de subklasse ze niet definieert.

Implementatiemethoden (overschrijf deze in een subklasse):

readinto(buf: bytearray) int | None

Lees bytes in de beschrijfbare buffer buf. Geeft het aantal gelezen bytes terug, 0 aan het einde van de stream, of None als er op dit moment geen gegevens beschikbaar zijn (voor een niet-blokkerende stream).

write(buf: bytes) int | None

Schrijf de bytes in buf. Geeft het aantal geschreven bytes terug, of None als de write op dit moment niet kan worden uitgevoerd (voor een niet-blokkerende stream).

ioctl(request: int, arg: int) int

Bestuur de onderliggende stream/het onderliggende apparaat. request is een van de MP_STREAM_*-requestcodes. Geeft bij succes een niet-negatieve waarde terug, of bij een fout een negatieve errno-waarde.

Streamprotocolmethoden (beschikbaar op elke streaminstantie):

read(size: int = -1)

Lees en geef maximaal size bytes terug (of tekens, in tekstmodus). Als size wordt weggelaten of negatief is, wordt er gelezen tot het einde van de stream. Geeft bytes terug voor binaire streams en str voor tekststreams; een leeg resultaat duidt op het einde van de stream.

readline(size: int = -1)

Lees en geef één regel terug, inclusief het afsluitende newline-teken als dat aanwezig is. Als size wordt opgegeven, worden er maximaal size bytes (of tekens) gelezen. Geeft een lege bytes / str terug aan het einde van de stream.

readlines() list

Lees tot het einde van de stream en geef een list met regels terug, elk met hun afsluitende newline.

close() None

Sluit de stream en geef alle onderliggende bronnen vrij. Bewerkingen op een gesloten stream werpen OSError (of ValueError voor streams in het geheugen).

seek(offset: int, whence: int = 0) int

Wijzig de huidige streampositie naar offset bytes ten opzichte van whence (0 = begin van de stream, 1 = huidige positie, 2 = einde van de stream). Geeft de nieuwe absolute positie terug. Werpt OSError op een stream die niet doorzoekbaar is.

tell() int

Geeft de huidige absolute positie in de stream terug. Equivalent aan seek(0, 1).

flush() None

Maak alle schrijfbuffers leeg en duw de openstaande gegevens naar het onderliggende apparaat of bestand. Een no-op op streams die niet bufferen.

Het rechtstreeks itereren over een stream levert per iteratie één regel op – equivalent aan het in een lus aanroepen van readline() totdat de lege-regel-sentinel voor het einde van de stream wordt teruggegeven. Een stream ondersteunt ook het contextmanagerprotocol, zodat with open(...) as f: de stream automatisch sluit.

Notitie

De streammodule van MicroPython stelt ook met “1” gesuffixte C-helpers mp_stream_read1_obj, mp_stream_readinto1_obj en mp_stream_write1_obj beschikbaar, die één enkele onderliggende I/O-aanroep uitvoeren in plaats van te blijven herhalen tot het verzoek volledig is afgehandeld. Ze worden intern gebruikt door klassen zoals machine.UART om hun eigen read / write te implementeren – maar geen enkele standaard streamklasse bindt ze als vanuit Python aanroepbare read1 / readinto1 / write1-methoden.

class io.StringIO(string: str = '')

Bestandachtig object in het geheugen voor invoer/uitvoer in tekstmodus (vergelijkbaar met een normaal bestand dat is geopend met de “t”-modifier). De initiële inhoud kan worden opgegeven met de parameter string (die een normale string moet zijn). Instanties ondersteunen ook het contextmanagerprotocol (bruikbaar in een with-statement).

read(size: int = -1) str

Lees en geef maximaal size tekens terug. Als size wordt weggelaten of negatief is, wordt alle resterende inhoud gelezen en teruggegeven.

readline(size: int = -1) str

Lees en geef één regel terug. Als size wordt opgegeven, worden er maximaal size tekens gelezen.

readinto(buf: bytearray) int

Lees in de vooraf toegewezen, beschrijfbare buffer buf en geef het aantal gelezen bytes terug.

write(s: str) int

Schrijf de string s en geef het aantal geschreven tekens terug.

seek(offset: int, whence: int = 0) int

Wijzig de streampositie naar offset ten opzichte van whence (0 = begin, 1 = huidige, 2 = einde) en geef de nieuwe absolute positie terug.

tell() int

Geeft de huidige streampositie terug.

flush() None

Maak de schrijfbuffers leeg. Dit is een no-op voor een stream in het geheugen.

close() None

Sluit de stream en geef de onderliggende buffer vrij. Verdere bewerkingen op een gesloten stream werpen ValueError.

getvalue() str

Geeft de huidige inhoud van de onderliggende buffer terug.

class io.StringIO(alloc_size: int)

Maak een leeg StringIO-object dat vooraf is toegewezen om maximaal alloc_size bytes te bevatten, zodat het schrijven van maximaal dat aantal bytes de buffer niet opnieuw zal toewijzen (waardoor een out-of-memory-situatie of geheugenfragmentatie wordt vermeden). Deze constructor is een MicroPython-uitbreiding die alleen wordt aanbevolen voor speciale gevallen en bibliotheken op systeemniveau, niet voor eindgebruikerstoepassingen.

Verschil met CPython

Deze constructor is een MicroPython-uitbreiding.

read(size: int = -1) str

Lees en geef maximaal size tekens terug. Als size wordt weggelaten of negatief is, wordt alle resterende inhoud gelezen en teruggegeven.

readline(size: int = -1) str

Lees en geef één regel terug. Als size wordt opgegeven, worden er maximaal size tekens gelezen.

readinto(buf: bytearray) int

Lees in de vooraf toegewezen, beschrijfbare buffer buf en geef het aantal gelezen bytes terug.

write(s: str) int

Schrijf de string s en geef het aantal geschreven tekens terug.

seek(offset: int, whence: int = 0) int

Wijzig de streampositie naar offset ten opzichte van whence (0 = begin, 1 = huidige, 2 = einde) en geef de nieuwe absolute positie terug.

tell() int

Geeft de huidige streampositie terug.

flush() None

Maak de schrijfbuffers leeg. Dit is een no-op voor een stream in het geheugen.

close() None

Sluit de stream en geef de onderliggende buffer vrij. Verdere bewerkingen op een gesloten stream werpen ValueError.

getvalue() str

Geeft de huidige inhoud van de onderliggende buffer terug.

class io.BytesIO(string: bytes = b'')

Bestandachtig object in het geheugen voor invoer/uitvoer in binaire modus (vergelijkbaar met een normaal bestand dat is geopend met de “b”-modifier). De initiële inhoud kan worden opgegeven met de parameter string (die een bytes-object moet zijn). Instanties ondersteunen ook het contextmanagerprotocol (bruikbaar in een with-statement).

read(size: int = -1) bytes

Lees en geef maximaal size bytes terug. Als size wordt weggelaten of negatief is, wordt alle resterende inhoud gelezen en teruggegeven.

readline(size: int = -1) bytes

Lees en geef één regel terug. Als size wordt opgegeven, worden er maximaal size bytes gelezen.

readinto(buf: bytearray) int

Lees in de vooraf toegewezen, beschrijfbare buffer buf en geef het aantal gelezen bytes terug.

write(b: bytes) int

Schrijf het bytes-achtige object b en geef het aantal geschreven bytes terug.

seek(offset: int, whence: int = 0) int

Wijzig de streampositie naar offset ten opzichte van whence (0 = begin, 1 = huidige, 2 = einde) en geef de nieuwe absolute positie terug.

tell() int

Geeft de huidige streampositie terug.

flush() None

Maak de schrijfbuffers leeg. Dit is een no-op voor een stream in het geheugen.

close() None

Sluit de stream en geef de onderliggende buffer vrij. Verdere bewerkingen op een gesloten stream werpen ValueError.

getvalue() bytes

Geeft de huidige inhoud van de onderliggende buffer terug.

class io.BytesIO(alloc_size: int)

Maak een leeg BytesIO-object dat vooraf is toegewezen om maximaal alloc_size bytes te bevatten, zodat het schrijven van maximaal dat aantal bytes de buffer niet opnieuw zal toewijzen (waardoor een out-of-memory-situatie of geheugenfragmentatie wordt vermeden). Deze constructor is een MicroPython-uitbreiding die alleen wordt aanbevolen voor speciale gevallen en bibliotheken op systeemniveau, niet voor eindgebruikerstoepassingen.

Verschil met CPython

Deze constructor is een MicroPython-uitbreiding.

read(size: int = -1) bytes

Lees en geef maximaal size bytes terug. Als size wordt weggelaten of negatief is, wordt alle resterende inhoud gelezen en teruggegeven.

readline(size: int = -1) bytes

Lees en geef één regel terug. Als size wordt opgegeven, worden er maximaal size bytes gelezen.

readinto(buf: bytearray) int

Lees in de vooraf toegewezen, beschrijfbare buffer buf en geef het aantal gelezen bytes terug.

write(b: bytes) int

Schrijf het bytes-achtige object b en geef het aantal geschreven bytes terug.

seek(offset: int, whence: int = 0) int

Wijzig de streampositie naar offset ten opzichte van whence (0 = begin, 1 = huidige, 2 = einde) en geef de nieuwe absolute positie terug.

tell() int

Geeft de huidige streampositie terug.

flush() None

Maak de schrijfbuffers leeg. Dit is een no-op voor een stream in het geheugen.

close() None

Sluit de stream en geef de onderliggende buffer vrij. Verdere bewerkingen op een gesloten stream werpen ValueError.

getvalue() bytes

Geeft de huidige inhoud van de onderliggende buffer terug.