micropython — acesso e controle dos internos do MicroPython

Funções

micropython.const(expr: int) int

Usada para declarar que a expressão é uma constante, de modo que o compilador possa otimizá-la. O uso desta função deve ser feito da seguinte forma:

from micropython import const

CONST_X = const(123)
CONST_Y = const(2 * CONST_X + 1)

Constantes declaradas dessa forma ainda são acessíveis como variáveis globais de fora do módulo em que são declaradas. Por outro lado, se uma constante começa com um sublinhado, então ela fica oculta, não fica disponível como variável global e não ocupa nenhuma memória durante a execução.

Esta função const é reconhecida diretamente pelo parser do MicroPython e é fornecida como parte do módulo micropython principalmente para que se possam escrever scripts que rodam tanto sob CPython quanto sob MicroPython, seguindo o padrão acima.

micropython.opt_level(level: int | None = None) int | None

Se level for fornecido, então esta função define o nível de otimização para compilações subsequentes de scripts e retorna None. Caso contrário, retorna o nível de otimização atual.

O nível de otimização controla as seguintes funcionalidades de compilação:

  • Asserções: no nível 0 as instruções assert ficam habilitadas e são compiladas no bytecode; nos níveis 1 e superiores as asserções não são compiladas.

  • Variável embutida __debug__: no nível 0 esta variável expande para True; nos níveis 1 e superiores ela expande para False.

  • Números de linha do código-fonte: nos níveis 0, 1 e 2 os números de linha do código-fonte são armazenados junto com o bytecode, de modo que as exceções possam reportar o número da linha em que ocorreram; nos níveis 3 e superiores os números de linha não são armazenados.

O nível de otimização padrão é geralmente o nível 0.

micropython.alloc_emergency_exception_buf(size: int) None

Aloca size bytes de RAM para o buffer de exceções de emergência (um bom tamanho é cerca de 100 bytes). O buffer é usado para criar exceções nos casos em que a alocação normal de RAM falharia (por exemplo, dentro de um handler de interrupção) e, portanto, fornece informações úteis de traceback nessas situações.

Uma boa maneira de usar esta função é colocá-la no início do seu script principal (por exemplo, boot.py ou main.py) e então o buffer de exceções de emergência ficará ativo para todo o código que vier depois.

micropython.mem_info(verbose: Any | None = None) None

Imprime informações sobre a memória atualmente em uso. Se o argumento verbose for fornecido, então informações extras são impressas.

As informações impressas dependem da implementação, mas atualmente incluem a quantidade de pilha e heap em uso. No modo verboso, ela imprime todo o heap, indicando quais blocos estão em uso e quais estão livres.

micropython.qstr_info(verbose: Any | None = None) None

Imprime informações sobre as strings atualmente internadas. Se o argumento verbose for fornecido, então informações extras são impressas.

As informações impressas dependem da implementação, mas atualmente incluem o número de strings internadas e a quantidade de RAM que elas usam. No modo verboso, ela imprime os nomes de todas as strings internadas em RAM.

micropython.stack_use() int

Retorna um inteiro representando a quantidade atual de pilha em uso. O valor absoluto disso não é particularmente útil; em vez disso, ele deve ser usado para calcular diferenças de uso de pilha em diferentes pontos.

micropython.heap_lock() None

Bloqueia o heap. Enquanto bloqueado, nenhuma alocação de memória pode ocorrer e um MemoryError será levantado se qualquer alocação de heap for tentada.

Os bloqueios são aninhados: chamar heap_lock() várias vezes aumenta a profundidade do bloqueio. O heap permanece bloqueado até que heap_unlock() tenha sido chamado o mesmo número de vezes.

Se o REPL se tornar ativo com o heap bloqueado, então ele será forçosamente desbloqueado.

micropython.heap_unlock() int

Decrementa a profundidade do bloqueio do heap em um e retorna a nova profundidade como um inteiro não negativo. Um valor de retorno 0 significa que o heap não está mais bloqueado e as alocações são novamente permitidas.

micropython.heap_locked() int

Retorna a profundidade atual do bloqueio do heap como um inteiro não negativo; 0 significa que o heap não está bloqueado.

Nota: esta função não está disponível na OpenMV Cam.

micropython.kbd_intr(chr: int) None

Define o caractere que levantará uma exceção KeyboardInterrupt. Por padrão, isso é definido como 3 durante a execução do script, correspondendo a Ctrl-C. Passar -1 para esta função desabilitará a captura de Ctrl-C, e passar 3 a restaurará.

Esta função pode ser usada para impedir a captura de Ctrl-C no fluxo de caracteres de entrada que normalmente é usado para o REPL, caso esse fluxo seja usado para outros fins.

micropython.schedule(func: Callable[[Any], Any], arg: Any) None

Agenda a função func para ser executada “muito em breve”. A função recebe o valor arg como seu único argumento. “Muito em breve” significa que o runtime do MicroPython fará o possível para executar a função o mais cedo possível, considerando que ele também está tentando ser eficiente e que as seguintes condições se aplicam:

  • Uma função agendada nunca interromperá outra função agendada.

  • Funções agendadas são sempre executadas “entre opcodes”, o que significa que todas as operações fundamentais do Python (como anexar a uma lista) têm a atomicidade garantida.

  • Uma determinada port pode definir “regiões críticas” dentro das quais funções agendadas nunca serão executadas. Funções podem ser agendadas dentro de uma região crítica, mas não serão executadas até que essa região seja deixada. Um exemplo de região crítica é um handler de interrupção que interrompe (uma IRQ).

  • Dentro de funções de código nativo, funções agendadas não são chamadas a menos que o código nativo chame uma função que faça isso especificamente.

  • Certas funções, incluindo poll.poll, poll.ipoll, time.sleep e time.sleep_ms (incluindo sleeps de duração zero), chamarão funções agendadas.

Um uso para esta função é agendar um callback a partir de uma IRQ que interrompe. Tal IRQ impõe restrições ao código que roda na IRQ (por exemplo, o heap pode estar bloqueado) e agendar uma função para chamar mais tarde levantará essas restrições.

Em ports multithread, o comportamento da função agendada depende de o Global Interpreter Lock (GIL) estar habilitado ou não para a port específica:

  • Se o GIL estiver habilitado, a função pode interromper qualquer thread e rodar em seu contexto.

  • Se o GIL estiver desabilitado, a função só interromperá a thread principal e rodará em seu contexto.

Nota: Se schedule() for chamada a partir de uma IRQ que interrompe, quando a alocação de memória não é permitida e o callback a ser passado para schedule() é um método vinculado, passá-lo diretamente falhará. Isso ocorre porque criar uma referência a um método vinculado causa alocação de memória. Uma solução é criar uma referência ao método no construtor da classe e passar essa referência para schedule(). Isso é discutido em detalhes aqui documentação de referência, em “Creation of Python objects”.

Há uma fila finita para conter as funções agendadas, e schedule() levantará um RuntimeError se a fila estiver cheia.

Classes

class micropython.RingIO(size: int)
class micropython.RingIO(buffer: bytes | bytearray | memoryview)

Fornece um ringbuffer de tamanho fixo para bytes com uma interface de stream. Pode ser considerado uma variante de fila FIFO de io.BytesIO. As duas formas do construtor diferem apenas em como o buffer de apoio é fornecido:

  • RingIO(size) aloca o buffer de apoio internamente. O algoritmo clássico de ringbuffer reserva um byte para rastreamento, então o buffer alocado é um byte maior que size e a instância pode conter os size bytes completos de dados. Por exemplo, RingIO(16) aloca um buffer de 17 bytes e contém 16 bytes de dados.

  • RingIO(buffer) usa o buffer fornecido no lugar, em vez de alocar um. Como um byte é reservado para rastreamento, a instância pode conter len(buffer) - 1 bytes de dados. Por exemplo, RingIO(bytearray(16)) contém 15 bytes de dados.

Uma instância de RingIO é segura para IRQ/thread quando usada para passar dados em uma única direção (por exemplo, escrita a partir de uma IRQ e lida a partir de uma função não-IRQ, ou vice-versa). Isso não vale se uma única instância for escrita tanto de contextos IRQ quanto não-IRQ, o que frequentemente causaria corrupção de dados.

any() int

Retorna um inteiro contando o número de caracteres que podem ser lidos.

read(nbytes: int | None = None) bytes

Lê os caracteres disponíveis. Esta é uma função não bloqueante. Se nbytes for especificado, então lê no máximo essa quantidade de bytes; caso contrário, lê o máximo de dados possível.

Valor de retorno: um objeto bytes contendo os bytes lidos. Será um objeto bytes de comprimento zero se nenhum dado estiver disponível.

readline(nbytes: int | None = None) bytes

Lê uma linha, terminando em um caractere de nova linha ou retorno se houver um no buffer, ou então retorna os bytes disponíveis no buffer. Se nbytes for especificado, então lê no máximo essa quantidade de bytes.

Valor de retorno: um objeto bytes contendo a linha lida.

readinto(buf: bytearray | memoryview, nbytes: int | None = None) int

Lê os bytes disponíveis para o buf fornecido. Se nbytes for especificado, então lê no máximo essa quantidade de bytes. Caso contrário, lê no máximo len(buf) bytes.

Valor de retorno: contagem inteira do número de bytes lidos para buf.

write(buf: bytes | bytearray | memoryview) int

Escrita não bloqueante de bytes de buf para o ringbuffer, limitada pelo espaço disponível no ringbuffer.

Valor de retorno: contagem inteira de bytes escritos.

close() None

No-op fornecido como parte da interface padrão stream. Não tem efeito sobre os dados no ringbuffer.