io — flujos de entrada/salida¶
Este módulo contiene tipos adicionales de objetos stream (similares a archivos) y funciones auxiliares. Expone la función integrada open() junto con búferes de texto y binarios en memoria (StringIO, BytesIO) que implementan la interfaz de flujo estándar read/write/seek.
Jerarquía conceptual¶
Diferencias con CPython
La jerarquía conceptual de las clases base de flujo está simplificada en MicroPython, tal como se describe en esta sección.
Las clases base de flujo (abstractas), que sirven de fundamento para el comportamiento de todas las clases concretas, se ajustan en CPython a unas pocas dicotomías (clasificaciones por pares). En MicroPython están algo simplificadas y se han hecho implícitas para lograr mayor eficiencia y ahorrar recursos.
Una dicotomía importante en CPython es la de los flujos sin búfer frente a los flujos con búfer. En MicroPython, todos los flujos carecen de búfer en la actualidad. Esto se debe a que todos los sistemas operativos modernos, e incluso muchos RTOS y controladores de sistemas de archivos, ya realizan el almacenamiento en búfer por su cuenta. Añadir otra capa de búfer resulta contraproducente (un problema conocido como «bufferbloat») y consume memoria valiosa. Ten en cuenta que aún existen casos en los que el búfer puede ser útil, por lo que es posible que introduzcamos soporte opcional de búfer más adelante.
Pero en CPython otra dicotomía importante está ligada a la «presencia de búfer»: se trata de si un flujo puede incurrir o no en lecturas/escrituras cortas. Una lectura corta ocurre cuando un usuario solicita, por ejemplo, 10 bytes de un flujo, pero recibe menos; lo mismo sucede con las escrituras. En CPython, los flujos sin búfer son automáticamente susceptibles a operaciones cortas, mientras que los flujos con búfer las garantizan en contra. La ausencia de lecturas/escrituras cortas es un rasgo importante, ya que permite desarrollar programas más concisos y eficientes, algo muy deseable para MicroPython. Así pues, aunque MicroPython no admite flujos con búfer, sí ofrece flujos sin operaciones cortas. El que haya o no operaciones cortas depende de las necesidades de cada clase concreta, pero se recomienda encarecidamente a los desarrolladores favorecer el comportamiento sin operaciones cortas por las razones expuestas anteriormente. Por ejemplo, los sockets de MicroPython tienen garantizado evitar las lecturas/escrituras cortas. De hecho, en este momento no hay ningún ejemplo de una clase de flujo con operaciones cortas en el núcleo, y dicha clase sería específica de un hardware concreto.
El comportamiento sin operaciones cortas se vuelve complicado en el caso de los flujos no bloqueantes; el comportamiento bloqueante frente al no bloqueante es otra dicotomía de CPython, totalmente admitida por MicroPython. Los flujos no bloqueantes nunca esperan a que los datos lleguen o se escriban: leen/escriben lo que sea posible o señalan la falta de datos (o de capacidad para escribir datos). Claramente, esto entra en conflicto con la política de «sin operaciones cortas» y, de hecho, el caso de los flujos no bloqueantes con búfer (y por tanto sin operaciones cortas) resulta enrevesado en CPython: en algunos lugares tal combinación está prohibida, en otros queda indefinida o simplemente sin documentar, y en algunos casos genera excepciones detalladas. El asunto es mucho más sencillo en MicroPython: los flujos no bloqueantes son importantes para operaciones asíncronas eficientes, por lo que esta propiedad prevalece sobre la de «sin operaciones cortas». Así, mientras que los flujos bloqueantes evitarán las lecturas/escrituras cortas siempre que sea posible (el único caso para obtener una lectura corta es si se alcanza el final del archivo, o en caso de error (aunque los errores no devuelven datos cortos, sino que generan excepciones)), los flujos no bloqueantes pueden producir datos cortos para evitar bloquear la operación.
La última dicotomía es la de los flujos binarios frente a los de texto. MicroPython, por supuesto, los admite, pero mientras que en CPython los flujos de texto tienen búfer de forma inherente, en MicroPython no lo tienen. (De hecho, ese es uno de los casos para los que podríamos introducir soporte de búfer).
Ten en cuenta que, por motivos de eficiencia, MicroPython no proporciona clases base abstractas que correspondan a la jerarquía anterior, y no es posible implementar ni heredar de una clase de flujo en Python puro.
Funciones¶
Clases¶
- class io.IOBase¶
Clase base para objetos de flujo (similares a archivos). Las subclases concretas implementan los métodos de E/S de bajo nivel que se indican a continuación (
readinto,write,ioctl); el entorno de ejecución construye sobre ellos el protocolo de flujo de más alto nivel (read,readline,readlines,close, iteración), de modo que toda instancia de flujo admite esos métodos incluso cuando la subclase no los define.Métodos de implementación (sobrescribe estos en una subclase):
- readinto(buf: bytearray) int | None¶
Lee bytes en el búfer escribible buf. Devuelve el número de bytes leídos,
0al final del flujo, oNonesi no hay datos disponibles en este momento (para un flujo no bloqueante).
- write(buf: bytes) int | None¶
Escribe los bytes de buf. Devuelve el número de bytes escritos, o
Nonesi la escritura no puede realizarse en este momento (para un flujo no bloqueante).
- ioctl(request: int, arg: int) int¶
Controla el flujo/dispositivo subyacente. request es uno de los códigos de solicitud
MP_STREAM_*. Devuelve un valor no negativo en caso de éxito, o un valorerrnonegativo en caso de error.
Métodos del protocolo de flujo (disponibles en toda instancia de flujo):
- read(size: int = -1)¶
Lee y devuelve hasta size bytes (o caracteres, en modo texto). Si se omite size o es negativo, lee hasta el final del flujo. Devuelve
bytespara flujos binarios ystrpara flujos de texto; un resultado vacío indica el final del flujo.
- readline(size: int = -1)¶
Lee y devuelve una línea, incluido el carácter de nueva línea final si está presente. Si se proporciona size, se leen como máximo size bytes (o caracteres). Devuelve un
bytes/strvacío al final del flujo.
- readlines() list¶
Lee hasta el final del flujo y devuelve una
listde líneas, cada una con su nueva línea final.
- close() None¶
Cierra el flujo y libera todos los recursos subyacentes. Las operaciones sobre un flujo cerrado generan
OSError(oValueErrorpara flujos en memoria).
- seek(offset: int, whence: int = 0) int¶
Cambia la posición actual del flujo a offset bytes con respecto a whence (
0= inicio del flujo,1= posición actual,2= final del flujo). Devuelve la nueva posición absoluta. GeneraOSErroren un flujo que no permite reposicionamiento.
- flush() None¶
Vacía cualquier búfer de escritura, enviando los datos pendientes al dispositivo o archivo subyacente. No tiene efecto en flujos que no usan búfer.
Iterar directamente sobre un flujo produce una línea por iteración, lo que equivale a llamar a
readline()en un bucle hasta que se devuelve el centinela de fin de flujo (línea vacía). Un flujo también admite el protocolo de gestor de contexto, de modo quewith open(...) as f:cierra el flujo automáticamente.Nota
El módulo de flujo de MicroPython también expone los ayudantes en C con sufijo «1»
mp_stream_read1_obj,mp_stream_readinto1_objymp_stream_write1_obj, que realizan una única llamada de E/S subyacente en lugar de iterar hasta satisfacer por completo la solicitud. Se usan internamente en clases comomachine.UARTpara implementar sus propiosread/write, pero ninguna clase de flujo estándar los vincula como métodosread1/readinto1/write1invocables desde Python.
- class io.StringIO(string: str = '')¶
Objeto en memoria similar a un archivo para entrada/salida en modo texto (similar a un archivo normal abierto con el modificador «t»). El contenido inicial puede especificarse con el parámetro string (que debe ser una cadena normal). Las instancias también admiten el protocolo de gestor de contexto (utilizable en una sentencia
with).- read(size: int = -1) str¶
Lee y devuelve hasta size caracteres. Si se omite size o es negativo, lee y devuelve todo el contenido restante.
- readline(size: int = -1) str¶
Lee y devuelve una línea. Si se proporciona size, se leen como máximo size caracteres.
- readinto(buf: bytearray) int¶
Lee en el búfer escribible preasignado buf y devuelve el número de bytes leídos.
- seek(offset: int, whence: int = 0) int¶
Cambia la posición del flujo a offset con respecto a whence (
0= inicio,1= actual,2= final) y devuelve la nueva posición absoluta.
- close() None¶
Cierra el flujo y libera el búfer subyacente. Las operaciones posteriores sobre un flujo cerrado generan
ValueError.
- class io.StringIO(alloc_size: int)
Crea un objeto
StringIOvacío preasignado para contener hasta alloc_size bytes, de modo que escribir hasta esa cantidad de bytes no reasignará el búfer (evitando una situación de falta de memoria o la fragmentación de la memoria). Este constructor es una extensión de MicroPython recomendada solo para casos especiales y bibliotecas de nivel de sistema, no para aplicaciones de usuario final.Diferencias con CPython
Este constructor es una extensión de MicroPython.
- read(size: int = -1) str
Lee y devuelve hasta size caracteres. Si se omite size o es negativo, lee y devuelve todo el contenido restante.
- readline(size: int = -1) str
Lee y devuelve una línea. Si se proporciona size, se leen como máximo size caracteres.
- readinto(buf: bytearray) int
Lee en el búfer escribible preasignado buf y devuelve el número de bytes leídos.
- seek(offset: int, whence: int = 0) int
Cambia la posición del flujo a offset con respecto a whence (
0= inicio,1= actual,2= final) y devuelve la nueva posición absoluta.
- tell() int
Devuelve la posición actual del flujo.
- flush() None
Vacía los búferes de escritura. No tiene efecto en un flujo en memoria.
- close() None
Cierra el flujo y libera el búfer subyacente. Las operaciones posteriores sobre un flujo cerrado generan
ValueError.
- getvalue() str
Devuelve el contenido actual del búfer subyacente.
- class io.BytesIO(string: bytes = b'')¶
Objeto en memoria similar a un archivo para entrada/salida en modo binario (similar a un archivo normal abierto con el modificador «b»). El contenido inicial puede especificarse con el parámetro string (que debe ser un objeto bytes). Las instancias también admiten el protocolo de gestor de contexto (utilizable en una sentencia
with).- read(size: int = -1) bytes¶
Lee y devuelve hasta size bytes. Si se omite size o es negativo, lee y devuelve todo el contenido restante.
- readline(size: int = -1) bytes¶
Lee y devuelve una línea. Si se proporciona size, se leen como máximo size bytes.
- readinto(buf: bytearray) int¶
Lee en el búfer escribible preasignado buf y devuelve el número de bytes leídos.
- seek(offset: int, whence: int = 0) int¶
Cambia la posición del flujo a offset con respecto a whence (
0= inicio,1= actual,2= final) y devuelve la nueva posición absoluta.
- close() None¶
Cierra el flujo y libera el búfer subyacente. Las operaciones posteriores sobre un flujo cerrado generan
ValueError.
- class io.BytesIO(alloc_size: int)
Crea un objeto
BytesIOvacío preasignado para contener hasta alloc_size bytes, de modo que escribir hasta esa cantidad de bytes no reasignará el búfer (evitando una situación de falta de memoria o la fragmentación de la memoria). Este constructor es una extensión de MicroPython recomendada solo para casos especiales y bibliotecas de nivel de sistema, no para aplicaciones de usuario final.Diferencias con CPython
Este constructor es una extensión de MicroPython.
- read(size: int = -1) bytes
Lee y devuelve hasta size bytes. Si se omite size o es negativo, lee y devuelve todo el contenido restante.
- readline(size: int = -1) bytes
Lee y devuelve una línea. Si se proporciona size, se leen como máximo size bytes.
- readinto(buf: bytearray) int
Lee en el búfer escribible preasignado buf y devuelve el número de bytes leídos.
- seek(offset: int, whence: int = 0) int
Cambia la posición del flujo a offset con respecto a whence (
0= inicio,1= actual,2= final) y devuelve la nueva posición absoluta.
- tell() int
Devuelve la posición actual del flujo.
- flush() None
Vacía los búferes de escritura. No tiene efecto en un flujo en memoria.
- close() None
Cierra el flujo y libera el búfer subyacente. Las operaciones posteriores sobre un flujo cerrado generan
ValueError.
- getvalue() bytes
Devuelve el contenido actual del búfer subyacente.