micropython — aceder e controlar os internos do MicroPython

Funções

micropython.const(expr: int) int

Utilizado para declarar que a expressão é uma constante, de modo a que o compilador a possa otimizar. A utilização desta função deve ser a seguinte:

from micropython import const

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

As constantes declaradas desta forma ainda são acessíveis como variáveis globais a partir de fora do módulo em que são declaradas. Por outro lado, se uma constante começar com um sublinhado, está oculta, não está disponível como variável global e não ocupa qualquer 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 os scripts possam ser escritos de forma a correr tanto no CPython como no MicroPython, seguindo o padrão acima.

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

Se level for fornecido, esta função define o nível de otimização para a compilação subsequente 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: ao nível 0, as instruções de asserção estão ativas e são compiladas para bytecode; nos níveis 1 e superiores, as asserções não são compiladas.

  • Variável integrada __debug__: ao nível 0, esta variável expande para True; nos níveis 1 e superiores, 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 juntamente com o bytecode para que as exceções possam indicar o número de 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 é normalmente o nível 0.

micropython.alloc_emergency_exception_buf(size: int) None

Aloca size bytes de RAM para o buffer de exceção de emergência (um bom tamanho é cerca de 100 bytes). O buffer é utilizado 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 rastreamento nessas situações.

Uma boa forma de utilizar esta função é colocá-la no início do seu script principal (por exemplo, boot.py ou main.py) e assim o buffer de exceção de emergência estará ativo para todo o código que se segue.

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

Imprime informações sobre a memória atualmente utilizada. Se o argumento verbose for fornecido, são impressas informações adicionais.

A informação impressa depende da implementação, mas atualmente inclui a quantidade de stack e heap utilizadas. No modo verbose, imprime toda a heap indicando quais os blocos que 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, são impressas informações adicionais.

A informação impressa depende da implementação, mas atualmente inclui o número de strings internadas e a quantidade de RAM que utilizam. No modo verbose, imprime os nomes de todas as strings internadas em RAM.

micropython.stack_use() int

Retorna um inteiro que representa a quantidade atual de stack em uso. O valor absoluto não é particularmente útil; serve antes para calcular diferenças no uso da stack em diferentes pontos.

micropython.heap_lock() None

Bloqueia a heap. Enquanto bloqueada, não pode ocorrer qualquer alocação de memória e será lançado um MemoryError se for tentada qualquer alocação na heap.

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

Se o REPL ficar ativo com a heap bloqueada, esta será desbloqueada forçosamente.

micropython.heap_unlock() int

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

micropython.heap_locked() int

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

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

micropython.kbd_intr(chr: int) None

Define o caráter que irá lançar uma exceção KeyboardInterrupt. Por padrão, este é definido como 3 durante a execução do script, correspondendo a Ctrl-C. Passar -1 a esta função desativa a captura de Ctrl-C, e passar 3 restaura-a.

Esta função pode ser utilizada para impedir a captura de Ctrl-C no fluxo de caracteres de entrada que normalmente é utilizado para o REPL, caso esse fluxo seja utilizado 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 único argumento. «Muito em breve» significa que o runtime do MicroPython fará o seu melhor para executar a função o mais cedo possível, tendo em conta que também tenta ser eficiente, e que as seguintes condições se verificam:

  • Uma função agendada nunca irá preemptar outra função agendada.

  • As funções agendadas são sempre executadas «entre opcodes», o que significa que todas as operações fundamentais de Python (como adicionar a uma lista) têm a garantia de ser atómicas.

  • Uma determinada porta pode definir «regiões críticas» nas quais as funções agendadas nunca serão executadas. As funções podem ser agendadas dentro de uma região crítica, mas não serão executadas até que essa região seja abandonada. Um exemplo de região crítica é um handler de interrupção preemptivo (um IRQ).

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

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

Uma utilização para esta função é agendar um callback a partir de um IRQ preemptivo. Tal IRQ impõe restrições ao código que corre no IRQ (por exemplo, a heap pode estar bloqueada) e agendar uma função para chamar mais tarde elimina essas restrições.

Em portas com múltiplas threads, o comportamento da função agendada depende de se o Global Interpreter Lock (GIL) está ativado para a porta específica:

  • Se o GIL estiver ativado, a função pode preemptar qualquer thread e correr no seu contexto.

  • Se o GIL estiver desativado, a função apenas irá preemptar a thread principal e correr no seu contexto.

Nota: Se schedule() for chamada a partir de um IRQ preemptivo, quando a alocação de memória não é permitida e o callback a ser passado a schedule() é um método vinculado, passá-lo diretamente falhará. Isto deve-se ao facto de criar uma referência a um método vinculado causar alocação de memória. Uma solução é criar uma referência ao método no construtor da classe e passar essa referência a schedule(). Isto é discutido em detalhe aqui documentação de referência em «Creation of Python objects».

Existe uma fila finita para guardar as funções agendadas e schedule() lançará 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 FIFO de io.BytesIO. As duas formas de construtor diferem apenas na forma como o buffer de suporte é fornecido:

  • RingIO(size) aloca o buffer de suporte internamente. O algoritmo clássico de ringbuffer reserva um byte para rastreamento, pelo que o buffer alocado tem um byte a mais do que size e a instância pode guardar os size bytes completos de dados. Por exemplo, RingIO(16) aloca um buffer de 17 bytes e guarda 16 bytes de dados.

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

Uma instância de RingIO é segura para IRQ/threads quando utilizada para passar dados numa única direção (por exemplo, escrita a partir de um IRQ e leitura a partir de uma função não-IRQ, ou vice-versa). Isto não se verifica se uma única instância for escrita tanto a partir de contextos IRQ como não-IRQ, o que frequentemente causaria corrupção de dados.

any() int

Retorna um inteiro com o número de carateres disponíveis para leitura.

read(nbytes: int | None = None) bytes

Lê os carateres disponíveis. Esta é uma função não bloqueante. Se nbytes for especificado, 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 não houver dados disponíveis.

readline(nbytes: int | None = None) bytes

Lê uma linha que termina num caráter de newline, ou retorna se existir uma no buffer; caso contrário, retorna os bytes disponíveis no buffer. Se nbytes for especificado, 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, 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 stream padrão. Não tem qualquer efeito nos dados do ringbuffer.