micropython — accesso e controllo degli interni di MicroPython¶
Funzioni¶
- micropython.const(expr: int) int¶
Utilizzata per dichiarare che l’espressione è una costante, in modo che il compilatore possa ottimizzarla. L’uso di questa funzione dovrebbe essere il seguente:
from micropython import const CONST_X = const(123) CONST_Y = const(2 * CONST_X + 1)
Le costanti dichiarate in questo modo restano accessibili come variabili globali dall’esterno del modulo in cui sono dichiarate. D’altra parte, se una costante inizia con un underscore allora è nascosta, non è disponibile come variabile globale e non occupa memoria durante l’esecuzione.
Questa funzione
constè riconosciuta direttamente dal parser di MicroPython ed è fornita come parte del modulomicropythonprincipalmente per consentire la scrittura di script che girano sia su CPython sia su MicroPython, seguendo lo schema sopra descritto.
- micropython.opt_level(level: int | None = None) int | None¶
Se viene fornito level, questa funzione imposta il livello di ottimizzazione per le successive compilazioni di script e restituisce
None. Altrimenti restituisce il livello di ottimizzazione corrente.Il livello di ottimizzazione controlla le seguenti funzionalità di compilazione:
Assert: al livello 0 le istruzioni assert sono abilitate e compilate nel bytecode; ai livelli 1 e superiori gli assert non vengono compilati.
Variabile incorporata
__debug__: al livello 0 questa variabile si espande inTrue; ai livelli 1 e superiori si espande inFalse.Numeri di riga del codice sorgente: ai livelli 0, 1 e 2 i numeri di riga del codice sorgente vengono memorizzati insieme al bytecode in modo che le eccezioni possano riportare il numero di riga in cui si sono verificate; ai livelli 3 e superiori i numeri di riga non vengono memorizzati.
Il livello di ottimizzazione predefinito è di solito il livello 0.
- micropython.alloc_emergency_exception_buf(size: int) None¶
Alloca size byte di RAM per il buffer delle eccezioni di emergenza (una buona dimensione è circa 100 byte). Il buffer viene utilizzato per creare eccezioni nei casi in cui la normale allocazione di RAM fallirebbe (ad esempio all’interno di un gestore di interrupt) e fornire quindi informazioni utili di traceback in queste situazioni.
Un buon modo per usare questa funzione è metterla all’inizio del tuo script principale (ad esempio
boot.pyomain.py); in tal modo il buffer delle eccezioni di emergenza sarà attivo per tutto il codice che lo segue.
- micropython.mem_info(verbose: Any | None = None) None¶
Stampa informazioni sulla memoria attualmente in uso. Se viene fornito l’argomento verbose, vengono stampate informazioni aggiuntive.
Le informazioni stampate dipendono dall’implementazione, ma attualmente includono la quantità di stack e heap utilizzata. In modalità verbose viene stampato l’intero heap indicando quali blocchi sono utilizzati e quali sono liberi.
- micropython.qstr_info(verbose: Any | None = None) None¶
Stampa informazioni sulle stringhe attualmente internate. Se viene fornito l’argomento verbose, vengono stampate informazioni aggiuntive.
Le informazioni stampate dipendono dall’implementazione, ma attualmente includono il numero di stringhe internate e la quantità di RAM che utilizzano. In modalità verbose vengono stampati i nomi di tutte le stringhe internate in RAM.
- micropython.stack_use() int¶
Restituisce un intero che rappresenta la quantità di stack attualmente in uso. Il suo valore assoluto non è particolarmente utile; va piuttosto usato per calcolare differenze nell’uso dello stack in punti diversi.
- micropython.heap_lock() None¶
Blocca l’heap. Mentre è bloccato, non può avvenire alcuna allocazione di memoria e verrà sollevato un
MemoryErrorse viene tentata una qualsiasi allocazione sull’heap.I blocchi si annidano: chiamare
heap_lock()più volte aumenta la profondità del blocco. L’heap rimane bloccato finchéheap_unlock()non è stata chiamata lo stesso numero di volte.Se il REPL diventa attivo mentre l’heap è bloccato, esso verrà sbloccato forzatamente.
- micropython.heap_unlock() int¶
Decrementa di uno la profondità del blocco dell’heap e restituisce la nuova profondità come intero non negativo. Un valore di ritorno di
0significa che l’heap non è più bloccato e le allocazioni sono nuovamente consentite.
- micropython.heap_locked() int¶
Restituisce la profondità corrente del blocco dell’heap come intero non negativo;
0significa che l’heap non è bloccato.Nota: questa funzione non è disponibile sulla OpenMV Cam.
- micropython.kbd_intr(chr: int) None¶
Imposta il carattere che solleverà un’eccezione
KeyboardInterrupt. Per impostazione predefinita questo è impostato a 3 durante l’esecuzione dello script, corrispondente a Ctrl-C. Passando -1 a questa funzione si disabilita la cattura di Ctrl-C, e passando 3 la si ripristina.Questa funzione può essere usata per impedire la cattura di Ctrl-C sul flusso di caratteri in ingresso che di solito viene usato per il REPL, nel caso in cui quel flusso sia usato per altri scopi.
- micropython.schedule(func: Callable[[Any], Any], arg: Any) None¶
Pianifica l’esecuzione «molto presto» della funzione func. Alla funzione viene passato il valore arg come unico argomento. «Molto presto» significa che il runtime di MicroPython farà del suo meglio per eseguire la funzione il prima possibile, tenendo conto del fatto che cerca anche di essere efficiente e che valgono le seguenti condizioni:
Una funzione pianificata non avrà mai la precedenza su un’altra funzione pianificata.
Le funzioni pianificate vengono sempre eseguite «tra gli opcode», il che significa che tutte le operazioni Python fondamentali (come l’aggiunta a una lista) sono garantite essere atomiche.
Una determinata porta può definire «regioni critiche» all’interno delle quali le funzioni pianificate non verranno mai eseguite. Le funzioni possono essere pianificate all’interno di una regione critica, ma non verranno eseguite finché quella regione non viene abbandonata. Un esempio di regione critica è un gestore di interrupt con prelazione (un IRQ).
All’interno di funzioni di codice nativo, le funzioni pianificate non vengono chiamate a meno che il codice nativo non chiami una funzione che lo fa specificamente.
Alcune funzioni, tra cui
poll.poll,poll.ipoll,time.sleepetime.sleep_ms(inclusi gli sleep di durata zero), chiameranno le funzioni pianificate.
Un uso di questa funzione è pianificare una callback da un IRQ con prelazione. Tale IRQ impone restrizioni sul codice che gira nell’IRQ (ad esempio l’heap può essere bloccato) e pianificare una funzione da chiamare in seguito rimuoverà tali restrizioni.
Sulle porte multi-thread, il comportamento della funzione pianificata dipende dal fatto che il Global Interpreter Lock (GIL) sia abilitato o meno per la porta specifica:
Se il GIL è abilitato, la funzione può prevalere su qualsiasi thread ed essere eseguita nel suo contesto.
Se il GIL è disabilitato, la funzione prevarrà solo sul thread principale e verrà eseguita nel suo contesto.
Nota: se
schedule()viene chiamata da un IRQ con prelazione, quando l’allocazione di memoria non è consentita e la callback da passare aschedule()è un metodo bound, passarla direttamente fallirà. Questo perché la creazione di un riferimento a un metodo bound provoca l’allocazione di memoria. Una soluzione è creare un riferimento al metodo nel costruttore della classe e passare quel riferimento aschedule(). Questo argomento è discusso in dettaglio qui documentazione di riferimento sotto «Creation of Python objects».Esiste una coda finita per contenere le funzioni pianificate e
schedule()solleverà unRuntimeErrorse la coda è piena.
Classi¶
- class micropython.RingIO(size: int)¶
- class micropython.RingIO(buffer: bytes | bytearray | memoryview)
Fornisce un ringbuffer a dimensione fissa per i byte con un’interfaccia stream. Può essere considerato una variante a coda FIFO di
io.BytesIO. Le due forme del costruttore differiscono solo nel modo in cui viene fornito il buffer di supporto:RingIO(size)alloca il buffer di supporto internamente. Il classico algoritmo del ringbuffer riserva un byte per il tracciamento, quindi il buffer allocato è un byte più grande disizee l’istanza può contenere l’intera quantità disizebyte di dati. Ad esempio,RingIO(16)alloca un buffer di 17 byte e contiene 16 byte di dati.RingIO(buffer)utilizza ilbufferfornito in loco invece di allocarne uno. Poiché un byte è riservato per il tracciamento, l’istanza può contenerelen(buffer) - 1byte di dati. Ad esempio,RingIO(bytearray(16))contiene 15 byte di dati.
Un’istanza di RingIO è sicura rispetto a IRQ/thread quando viene usata per passare dati in una sola direzione (ad esempio scritta da un IRQ e letta da una funzione non-IRQ, o viceversa). Questo non vale se una singola istanza viene scritta sia da contesti IRQ sia non-IRQ, il che spesso causerebbe la corruzione dei dati.
- read(nbytes: int | None = None) bytes¶
Legge i caratteri disponibili. Questa è una funzione non bloccante. Se viene specificato
nbytesallora legge al massimo quel numero di byte, altrimenti legge quanti più dati possibile.Valore restituito: un oggetto bytes contenente i byte letti. Sarà un oggetto bytes di lunghezza zero se non ci sono dati disponibili.
- readline(nbytes: int | None = None) bytes¶
Legge una riga, terminante con un carattere di newline o return se ne esiste uno nel buffer, altrimenti restituisce i byte disponibili nel buffer. Se viene specificato
nbytesallora legge al massimo quel numero di byte.Valore restituito: un oggetto bytes contenente la riga letta.
- readinto(buf: bytearray | memoryview, nbytes: int | None = None) int¶
Legge i byte disponibili nel
buffornito. Se viene specificatonbytesallora legge al massimo quel numero di byte. Altrimenti, legge al massimolen(buf)byte.Valore restituito: conteggio intero del numero di byte letti in
buf.
- write(buf: bytes | bytearray | memoryview) int¶
Scrittura non bloccante di byte da
bufnel ringbuffer, limitata dallo spazio disponibile nel ringbuffer.Valore restituito: conteggio intero dei byte scritti.