io — flux d’entrée/sortie¶
Ce module contient des types supplémentaires d’objets stream (de type fichier) ainsi que des fonctions utilitaires. Il expose la fonction native open() ainsi que des tampons texte et binaires en mémoire (StringIO, BytesIO) qui implémentent l’interface de flux standard read/write/seek.
Hiérarchie conceptuelle¶
Différence avec CPython
La hiérarchie conceptuelle des classes de base de flux est simplifiée dans MicroPython, comme décrit dans cette section.
Les classes de flux de base (abstraites), qui servent de fondation au comportement de toutes les classes concrètes, respectent quelques dichotomies (classifications par paires) dans CPython. Dans MicroPython, elles sont quelque peu simplifiées et rendues implicites afin d’atteindre une meilleure efficacité et d’économiser les ressources.
Une dichotomie importante dans CPython est celle des flux avec tampon (buffered) ou sans tampon (unbuffered). Dans MicroPython, tous les flux sont actuellement sans tampon. C’est parce que tous les systèmes d’exploitation modernes, et même de nombreux RTOS et pilotes de système de fichiers, effectuent déjà une mise en tampon de leur côté. Ajouter une autre couche de mise en tampon est contre-productif (un problème connu sous le nom de « bufferbloat ») et consomme de la mémoire précieuse. Notez qu’il existe encore des cas où la mise en tampon peut être utile, donc nous pourrions introduire une prise en charge optionnelle de la mise en tampon ultérieurement.
Mais dans CPython, une autre dichotomie importante est liée à la « mise en tampon » : c’est de savoir si un flux peut subir des lectures/écritures partielles ou non. Une lecture partielle se produit lorsqu’un utilisateur demande par exemple 10 octets à un flux, mais en obtient moins ; de même pour les écritures. Dans CPython, les flux sans tampon sont automatiquement susceptibles d’opérations partielles, tandis que les flux avec tampon en sont garantis exempts. L’absence de lectures/écritures partielles est un trait important, car elle permet de développer des programmes plus concis et efficaces - chose hautement souhaitable pour MicroPython. Ainsi, bien que MicroPython ne prenne pas en charge les flux avec tampon, il fournit néanmoins des flux sans opérations partielles. La présence ou non d’opérations partielles dépend des besoins de chaque classe particulière, mais il est fortement conseillé aux développeurs de privilégier le comportement sans opérations partielles pour les raisons exposées ci-dessus. Par exemple, les sockets MicroPython sont garantis d’éviter les lectures/écritures partielles. En réalité, à l’heure actuelle, il n’existe aucun exemple de classe de flux à opérations partielles dans le cœur, et une telle classe serait spécifique à un matériel particulier.
Le comportement sans opérations partielles devient délicat dans le cas des flux non bloquants, le comportement bloquant ou non bloquant étant une autre dichotomie de CPython, entièrement prise en charge par MicroPython. Les flux non bloquants n’attendent jamais que des données arrivent ou soient écrites - ils lisent/écrivent ce qui est possible, ou signalent l’absence de données (ou la capacité d’écrire des données). De toute évidence, cela entre en conflit avec la politique « sans opérations partielles », et en effet, le cas des flux non bloquants avec tampon (et donc sans opérations partielles) est alambiqué dans CPython - à certains endroits, une telle combinaison est interdite, à d’autres elle est indéfinie ou simplement non documentée, et dans certains cas elle lève des exceptions verbeuses. La question est beaucoup plus simple dans MicroPython : les flux non bloquants sont importants pour des opérations asynchrones efficaces, donc cette propriété prévaut sur celle de l”« absence d’opérations partielles ». Ainsi, alors que les flux bloquants éviteront les lectures/écritures partielles dans la mesure du possible (le seul cas où l’on obtient une lecture partielle est lorsque la fin du fichier est atteinte, ou en cas d’erreur (mais les erreurs ne renvoient pas de données partielles, elles lèvent des exceptions)), les flux non bloquants peuvent produire des données partielles afin d’éviter de bloquer l’opération.
La dernière dichotomie est celle des flux binaires ou texte. MicroPython prend bien sûr en charge ces deux types, mais alors que dans CPython les flux texte sont intrinsèquement mis en tampon, ils ne le sont pas dans MicroPython. (En effet, c’est l’un des cas pour lesquels nous pourrions introduire la prise en charge de la mise en tampon.)
Notez que pour des raisons d’efficacité, MicroPython ne fournit pas de classes de base abstraites correspondant à la hiérarchie ci-dessus, et il n’est pas possible d’implémenter, ou de dériver, une classe de flux en pur Python.
Fonctions¶
Classes¶
- class io.IOBase¶
Classe de base pour les objets de flux (de type « fichier »). Les sous-classes concrètes implémentent les méthodes d’E/S de bas niveau ci-dessous (
readinto,write,ioctl) ; le runtime construit le protocole de flux de plus haut niveau (read,readline,readlines,close, itération) par-dessus, de sorte que chaque instance de flux prend en charge ces méthodes même lorsque la sous-classe ne les définit pas.Méthodes d’implémentation (à redéfinir dans une sous-classe) :
- readinto(buf: bytearray) int | None¶
Lit des octets dans le tampon accessible en écriture buf. Renvoie le nombre d’octets lus,
0en fin de flux, ouNonesi aucune donnée n’est disponible pour le moment (pour un flux non bloquant).
- write(buf: bytes) int | None¶
Écrit les octets contenus dans buf. Renvoie le nombre d’octets écrits, ou
Nonesi l’écriture ne peut pas être effectuée pour le moment (pour un flux non bloquant).
- ioctl(request: int, arg: int) int¶
Contrôle le flux/périphérique sous-jacent. request est l’un des codes de requête
MP_STREAM_*. Renvoie une valeur non négative en cas de succès, ou une valeurerrnonégative en cas d’erreur.
Méthodes du protocole de flux (disponibles sur chaque instance de flux) :
- read(size: int = -1)¶
Lit et renvoie jusqu’à size octets (ou caractères, en mode texte). Si size est omis ou négatif, lit jusqu’à la fin du flux. Renvoie
bytespour les flux binaires etstrpour les flux texte ; un résultat vide indique la fin du flux.
- readline(size: int = -1)¶
Lit et renvoie une ligne, y compris le caractère de fin de ligne s’il est présent. Si size est fourni, au plus size octets (ou caractères) sont lus. Renvoie une chaîne
bytes/strvide en fin de flux.
- readlines() list¶
Lit jusqu’à la fin du flux et renvoie une
listde lignes, chacune avec son caractère de fin de ligne.
- close() None¶
Ferme le flux et libère toutes les ressources sous-jacentes. Les opérations sur un flux fermé lèvent
OSError(ouValueErrorpour les flux en mémoire).
- seek(offset: int, whence: int = 0) int¶
Change la position courante du flux à offset octets relativement à whence (
0= début du flux,1= position courante,2= fin du flux). Renvoie la nouvelle position absolue. LèveOSErrorsur un flux qui n’est pas positionnable.
- flush() None¶
Vide tous les tampons d’écriture, en poussant les données en attente vers le périphérique ou le fichier sous-jacent. Sans effet sur les flux qui n’utilisent pas de tampon.
Itérer directement sur un flux produit une ligne par itération – équivalent à appeler
readline()dans une boucle jusqu’à ce que la sentinelle de fin de flux (ligne vide) soit renvoyée. Un flux prend également en charge le protocole de gestionnaire de contexte, de sorte quewith open(...) as f:ferme le flux automatiquement.Note
Le module de flux de MicroPython expose également des fonctions utilitaires C suffixées par « 1 » :
mp_stream_read1_obj,mp_stream_readinto1_objetmp_stream_write1_obj, qui effectuent un seul appel d’E/S sous-jacent au lieu de boucler jusqu’à ce que la requête soit entièrement satisfaite. Elles sont utilisées en interne par des classes commemachine.UARTpour implémenter leurs propresread/write– mais aucune classe de flux standard ne les lie en tant que méthodesread1/readinto1/write1appelables depuis Python.
- class io.StringIO(string: str = '')¶
Objet en mémoire de type fichier pour les entrées/sorties en mode texte (similaire à un fichier normal ouvert avec le modificateur « t »). Le contenu initial peut être spécifié avec le paramètre string (qui doit être une chaîne normale). Les instances prennent également en charge le protocole de gestionnaire de contexte (utilisable dans une instruction
with).- read(size: int = -1) str¶
Lit et renvoie jusqu’à size caractères. Si size est omis ou négatif, lit et renvoie tout le contenu restant.
- readline(size: int = -1) str¶
Lit et renvoie une ligne. Si size est fourni, au plus size caractères sont lus.
- readinto(buf: bytearray) int¶
Lit dans le tampon préalloué et accessible en écriture buf et renvoie le nombre d’octets lus.
- seek(offset: int, whence: int = 0) int¶
Change la position du flux à offset relativement à whence (
0= début,1= position courante,2= fin) et renvoie la nouvelle position absolue.
- close() None¶
Ferme le flux et libère le tampon sous-jacent. Toute opération ultérieure sur un flux fermé lève
ValueError.
- class io.StringIO(alloc_size: int)
Crée un objet
StringIOvide préalloué pour contenir jusqu’à alloc_size octets, de sorte que l’écriture de ce nombre d’octets ne réallouera pas le tampon (évitant une situation de manque de mémoire ou la fragmentation de la mémoire). Ce constructeur est une extension de MicroPython recommandée uniquement pour des cas particuliers et les bibliothèques de niveau système, pas pour les applications utilisateur final.Différence avec CPython
Ce constructeur est une extension de MicroPython.
- read(size: int = -1) str
Lit et renvoie jusqu’à size caractères. Si size est omis ou négatif, lit et renvoie tout le contenu restant.
- readline(size: int = -1) str
Lit et renvoie une ligne. Si size est fourni, au plus size caractères sont lus.
- readinto(buf: bytearray) int
Lit dans le tampon préalloué et accessible en écriture buf et renvoie le nombre d’octets lus.
- seek(offset: int, whence: int = 0) int
Change la position du flux à offset relativement à whence (
0= début,1= position courante,2= fin) et renvoie la nouvelle position absolue.
- tell() int
Renvoie la position courante du flux.
- flush() None
Vide les tampons d’écriture. Cela est sans effet pour un flux en mémoire.
- close() None
Ferme le flux et libère le tampon sous-jacent. Toute opération ultérieure sur un flux fermé lève
ValueError.
- getvalue() str
Renvoie le contenu courant du tampon sous-jacent.
- class io.BytesIO(string: bytes = b'')¶
Objet en mémoire de type fichier pour les entrées/sorties en mode binaire (similaire à un fichier normal ouvert avec le modificateur « b »). Le contenu initial peut être spécifié avec le paramètre string (qui doit être un objet bytes). Les instances prennent également en charge le protocole de gestionnaire de contexte (utilisable dans une instruction
with).- read(size: int = -1) bytes¶
Lit et renvoie jusqu’à size octets. Si size est omis ou négatif, lit et renvoie tout le contenu restant.
- readline(size: int = -1) bytes¶
Lit et renvoie une ligne. Si size est fourni, au plus size octets sont lus.
- readinto(buf: bytearray) int¶
Lit dans le tampon préalloué et accessible en écriture buf et renvoie le nombre d’octets lus.
- seek(offset: int, whence: int = 0) int¶
Change la position du flux à offset relativement à whence (
0= début,1= position courante,2= fin) et renvoie la nouvelle position absolue.
- close() None¶
Ferme le flux et libère le tampon sous-jacent. Toute opération ultérieure sur un flux fermé lève
ValueError.
- class io.BytesIO(alloc_size: int)
Crée un objet
BytesIOvide préalloué pour contenir jusqu’à alloc_size octets, de sorte que l’écriture de ce nombre d’octets ne réallouera pas le tampon (évitant une situation de manque de mémoire ou la fragmentation de la mémoire). Ce constructeur est une extension de MicroPython recommandée uniquement pour des cas particuliers et les bibliothèques de niveau système, pas pour les applications utilisateur final.Différence avec CPython
Ce constructeur est une extension de MicroPython.
- read(size: int = -1) bytes
Lit et renvoie jusqu’à size octets. Si size est omis ou négatif, lit et renvoie tout le contenu restant.
- readline(size: int = -1) bytes
Lit et renvoie une ligne. Si size est fourni, au plus size octets sont lus.
- readinto(buf: bytearray) int
Lit dans le tampon préalloué et accessible en écriture buf et renvoie le nombre d’octets lus.
- seek(offset: int, whence: int = 0) int
Change la position du flux à offset relativement à whence (
0= début,1= position courante,2= fin) et renvoie la nouvelle position absolue.
- tell() int
Renvoie la position courante du flux.
- flush() None
Vide les tampons d’écriture. Cela est sans effet pour un flux en mémoire.
- close() None
Ferme le flux et libère le tampon sous-jacent. Toute opération ultérieure sur un flux fermé lève
ValueError.
- getvalue() bytes
Renvoie le contenu courant du tampon sous-jacent.