io — fluxos de entrada/saída

Este módulo contém tipos adicionais de objetos stream (semelhantes a ficheiros) e funções auxiliares. Expõe a função incorporada open() juntamente com buffers de texto e binários em memória (StringIO, BytesIO) que implementam a interface padrão de fluxo read/write/seek.

Hierarquia conceptual

Diferença em relação ao CPython

A hierarquia conceptual de classes base de fluxos é simplificada no MicroPython, conforme descrito nesta secção.

As classes base (abstratas) de fluxo, que servem de fundação para o comportamento de todas as classes concretas, obedecem a algumas dicotomias (classificações aos pares) no CPython. No MicroPython, estas são de certo modo simplificadas e tornadas implícitas para alcançar maior eficiência e poupar recursos.

Uma dicotomia importante no CPython é a de fluxos com e sem buffer. No MicroPython, todos os fluxos são atualmente sem buffer. Isto deve-se ao facto de todos os sistemas operativos modernos, e até muitos RTOS e controladores de sistemas de ficheiros, já realizarem buffering do seu lado. Adicionar mais uma camada de buffering é contraproducente (um problema conhecido como «bufferbloat») e consome memória preciosa. Note-se que ainda existem casos em que o buffering pode ser útil, pelo que poderemos introduzir suporte opcional de buffering numa fase posterior.

Mas no CPython, outra dicotomia importante está ligada ao «buffering» – se um fluxo pode ou não sofrer leituras/escritas curtas. Uma leitura curta ocorre quando o utilizador pede, por exemplo, 10 bytes de um fluxo, mas recebe menos; o mesmo se aplica às escritas. No CPython, os fluxos sem buffer ficam automaticamente sujeitos a operações curtas, enquanto os com buffer garantem a sua ausência. A ausência de leituras/escritas curtas é uma característica importante, pois permite desenvolver programas mais concisos e eficientes – algo altamente desejável no MicroPython. Assim, embora o MicroPython não suporte fluxos com buffer, oferece fluxos sem operações curtas. Se existirão ou não operações curtas depende das necessidades de cada classe em particular, mas recomenda-se vivamente aos programadores que privilegiem o comportamento sem operações curtas, pelas razões acima indicadas. Por exemplo, os sockets do MicroPython garantem a ausência de leituras/escritas curtas. De facto, neste momento não existe nenhum exemplo de classe de fluxo com operações curtas no núcleo, e tal classe seria específica para hardware particular.

O comportamento sem operações curtas torna-se complicado no caso de fluxos não bloqueantes – o comportamento bloqueante versus não bloqueante sendo outra dicotomia do CPython, totalmente suportada pelo MicroPython. Os fluxos não bloqueantes nunca aguardam pela chegada de dados nem pela possibilidade de escrever – leem/escrevem o que for possível, ou sinalizam a ausência de dados (ou a incapacidade de escrever dados). Claramente, isto entra em conflito com a política de «sem operações curtas» e, de facto, a combinação de fluxos não bloqueantes com buffer (e portanto sem operações curtas) é complicada no CPython – em alguns locais tal combinação é proibida, noutros é indefinida ou simplesmente não documentada, e noutros ainda levanta exceções prolixas. A questão é muito mais simples no MicroPython: os fluxos não bloqueantes são importantes para operações assíncronas eficientes, pelo que esta propriedade prevalece sobre a de «sem operações curtas». Assim, enquanto os fluxos bloqueantes evitarão leituras/escritas curtas sempre que possível (o único caso em que ocorre uma leitura curta é ao atingir o fim do ficheiro, ou em caso de erro – mas os erros não devolvem dados curtos, levantam exceções), os fluxos não bloqueantes podem produzir dados curtos para evitar bloquear a operação.

A dicotomia final é entre fluxos binários e de texto. O MicroPython suporta naturalmente ambos, mas enquanto no CPython os fluxos de texto são inerentemente com buffer, no MicroPython não são. (De facto, esse é um dos casos para os quais poderemos introduzir suporte de buffering.)

Note-se que, por razões de eficiência, o MicroPython não fornece classes base abstratas correspondentes à hierarquia acima, e não é possível implementar nem derivar uma classe de fluxo em Python puro.

Funções

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

Abre um ficheiro. A função incorporada open() é um alias para esta função. O parâmetro mode é sempre suportado; o suporte para outros argumentos pode variar.

Classes

class io.IOBase

Classe base para objetos de fluxo («semelhantes a ficheiros»). As subclasses concretas implementam os métodos I/O de baixo nível abaixo (readinto, write, ioctl); o runtime constrói o protocolo de fluxo de alto nível (read, readline, readlines, close, iteração) sobre eles, pelo que todas as instâncias de fluxo suportam esses métodos mesmo quando a subclasse não os define.

Métodos de implementação (redefina-os numa subclasse):

readinto(buf: bytearray) int | None

Lê bytes para o buffer gravável buf. Devolve o número de bytes lidos, 0 no fim do fluxo, ou None se não houver dados disponíveis neste momento (para um fluxo não bloqueante).

write(buf: bytes) int | None

Escreve os bytes em buf. Devolve o número de bytes escritos, ou None se a escrita não puder ser realizada neste momento (para um fluxo não bloqueante).

ioctl(request: int, arg: int) int

Controla o fluxo/dispositivo subjacente. request é um dos códigos de pedido MP_STREAM_*. Devolve um valor não negativo em caso de sucesso, ou um valor negativo errno em caso de erro.

Métodos do protocolo de fluxo (disponíveis em todas as instâncias de fluxo):

read(size: int = -1)

Lê e devolve até size bytes (ou caracteres, em modo de texto). Se size for omitido ou negativo, lê até ao fim do fluxo. Devolve bytes para fluxos binários e str para fluxos de texto; um resultado vazio indica o fim do fluxo.

readline(size: int = -1)

Lê e devolve uma linha, incluindo o carácter de nova linha final, se presente. Se size for especificado, são lidos no máximo size bytes (ou caracteres). Devolve um bytes / str vazio no fim do fluxo.

readlines() list

Lê até ao fim do fluxo e devolve uma list de linhas, cada uma com a sua nova linha final.

close() None

Fecha o fluxo e liberta quaisquer recursos subjacentes. Operações sobre um fluxo fechado levantam OSError (ou ValueError para fluxos em memória).

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

Altera a posição atual do fluxo para offset bytes em relação a whence (0 = início do fluxo, 1 = posição atual, 2 = fim do fluxo). Devolve a nova posição absoluta. Lança OSError num fluxo que não seja posicionável.

tell() int

Devolve a posição absoluta atual no fluxo. Equivalente a seek(0, 1).

flush() None

Descarrega quaisquer buffers de escrita, enviando os dados pendentes para o dispositivo ou ficheiro subjacente. Não tem efeito em fluxos que não utilizem buffer.

Iterar diretamente sobre um fluxo produz uma linha por iteração – equivalente a chamar readline() em ciclo até ser devolvida a sentinela de fim de fluxo (linha vazia). Um fluxo também suporta o protocolo de gestor de contexto, pelo que with open(...) as f: fecha o fluxo automaticamente.

Nota

O módulo de fluxo do MicroPython também expõe auxiliares C com sufixo «1» – mp_stream_read1_obj, mp_stream_readinto1_obj e mp_stream_write1_obj – que realizam uma única chamada I/O subjacente em vez de iterar até à satisfação completa do pedido. São utilizados internamente por classes como machine.UART para implementar os seus próprios read / write – mas nenhuma classe de fluxo padrão os disponibiliza como métodos Python-invocáveis read1 / readinto1 / write1.

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

Objeto semelhante a ficheiro em memória para entrada/saída em modo de texto (semelhante a um ficheiro normal aberto com o modificador «t»). O conteúdo inicial pode ser especificado com o parâmetro string (que deverá ser uma string normal). As instâncias também suportam o protocolo de gestor de contexto (utilizável numa instrução with).

read(size: int = -1) str

Lê e devolve até size caracteres. Se size for omitido ou negativo, lê e devolve todo o conteúdo restante.

readline(size: int = -1) str

Lê e devolve uma linha. Se size for especificado, são lidos no máximo size caracteres.

readinto(buf: bytearray) int

Lê para o buffer gravável pré-alocado buf e devolve o número de bytes lidos.

write(s: str) int

Escreve a string s e devolve o número de caracteres escritos.

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

Altera a posição do fluxo para offset em relação a whence (0 = início, 1 = atual, 2 = fim) e devolve a nova posição absoluta.

tell() int

Devolve a posição atual do fluxo.

flush() None

Descarrega os buffers de escrita. Esta operação não tem efeito para um fluxo em memória.

close() None

Fecha o fluxo e liberta o buffer subjacente. Operações posteriores sobre um fluxo fechado levantam ValueError.

getvalue() str

Devolve o conteúdo atual do buffer subjacente.

class io.StringIO(alloc_size: int)

Cria um objeto StringIO vazio pré-alocado para conter até alloc_size bytes, de modo que escrever até esse número de bytes não irá realocar o buffer (evitando uma situação de falta de memória ou fragmentação de memória). Este construtor é uma extensão do MicroPython recomendada apenas para casos especiais e bibliotecas de sistema, não para aplicações de utilizador final.

Diferença em relação ao CPython

Este construtor é uma extensão do MicroPython.

read(size: int = -1) str

Lê e devolve até size caracteres. Se size for omitido ou negativo, lê e devolve todo o conteúdo restante.

readline(size: int = -1) str

Lê e devolve uma linha. Se size for especificado, são lidos no máximo size caracteres.

readinto(buf: bytearray) int

Lê para o buffer gravável pré-alocado buf e devolve o número de bytes lidos.

write(s: str) int

Escreve a string s e devolve o número de caracteres escritos.

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

Altera a posição do fluxo para offset em relação a whence (0 = início, 1 = atual, 2 = fim) e devolve a nova posição absoluta.

tell() int

Devolve a posição atual do fluxo.

flush() None

Descarrega os buffers de escrita. Esta operação não tem efeito para um fluxo em memória.

close() None

Fecha o fluxo e liberta o buffer subjacente. Operações posteriores sobre um fluxo fechado levantam ValueError.

getvalue() str

Devolve o conteúdo atual do buffer subjacente.

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

Objeto semelhante a ficheiro em memória para entrada/saída em modo binário (semelhante a um ficheiro normal aberto com o modificador «b»). O conteúdo inicial pode ser especificado com o parâmetro string (que deverá ser um objeto bytes). As instâncias também suportam o protocolo de gestor de contexto (utilizável numa instrução with).

read(size: int = -1) bytes

Lê e devolve até size bytes. Se size for omitido ou negativo, lê e devolve todo o conteúdo restante.

readline(size: int = -1) bytes

Lê e devolve uma linha. Se size for especificado, são lidos no máximo size bytes.

readinto(buf: bytearray) int

Lê para o buffer gravável pré-alocado buf e devolve o número de bytes lidos.

write(b: bytes) int

Escreve o objeto bytes b e devolve o número de bytes escritos.

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

Altera a posição do fluxo para offset em relação a whence (0 = início, 1 = atual, 2 = fim) e devolve a nova posição absoluta.

tell() int

Devolve a posição atual do fluxo.

flush() None

Descarrega os buffers de escrita. Esta operação não tem efeito para um fluxo em memória.

close() None

Fecha o fluxo e liberta o buffer subjacente. Operações posteriores sobre um fluxo fechado levantam ValueError.

getvalue() bytes

Devolve o conteúdo atual do buffer subjacente.

class io.BytesIO(alloc_size: int)

Cria um objeto BytesIO vazio pré-alocado para conter até alloc_size bytes, de modo que escrever até esse número de bytes não irá realocar o buffer (evitando uma situação de falta de memória ou fragmentação de memória). Este construtor é uma extensão do MicroPython recomendada apenas para casos especiais e bibliotecas de sistema, não para aplicações de utilizador final.

Diferença em relação ao CPython

Este construtor é uma extensão do MicroPython.

read(size: int = -1) bytes

Lê e devolve até size bytes. Se size for omitido ou negativo, lê e devolve todo o conteúdo restante.

readline(size: int = -1) bytes

Lê e devolve uma linha. Se size for especificado, são lidos no máximo size bytes.

readinto(buf: bytearray) int

Lê para o buffer gravável pré-alocado buf e devolve o número de bytes lidos.

write(b: bytes) int

Escreve o objeto bytes b e devolve o número de bytes escritos.

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

Altera a posição do fluxo para offset em relação a whence (0 = início, 1 = atual, 2 = fim) e devolve a nova posição absoluta.

tell() int

Devolve a posição atual do fluxo.

flush() None

Descarrega os buffers de escrita. Esta operação não tem efeito para um fluxo em memória.

close() None

Fecha o fluxo e liberta o buffer subjacente. Operações posteriores sobre um fluxo fechado levantam ValueError.

getvalue() bytes

Devolve o conteúdo atual do buffer subjacente.