micropython — accès et contrôle des éléments internes de MicroPython

Fonctions

micropython.const(expr: int) int

Sert à déclarer qu’une expression est une constante afin que le compilateur puisse l’optimiser. L’utilisation de cette fonction doit se faire comme suit

from micropython import const

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

Les constantes déclarées de cette manière restent accessibles en tant que variables globales depuis l’extérieur du module dans lequel elles sont déclarées. En revanche, si une constante commence par un trait de soulignement, elle est masquée, n’est pas disponible en tant que variable globale et n’occupe aucune mémoire pendant l’exécution.

Cette fonction const est reconnue directement par l’analyseur de MicroPython et est fournie dans le cadre du module micropython principalement pour que des scripts puissent être écrits de façon à fonctionner à la fois sous CPython et MicroPython, en suivant le modèle ci-dessus.

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

Si level est fourni, cette fonction définit le niveau d’optimisation pour les compilations ultérieures de scripts et renvoie None. Sinon, elle renvoie le niveau d’optimisation actuel.

Le niveau d’optimisation contrôle les fonctionnalités de compilation suivantes :

  • Assertions : au niveau 0, les instructions d’assertion sont activées et compilées dans le bytecode ; aux niveaux 1 et supérieurs, les assertions ne sont pas compilées.

  • Variable intégrée __debug__ : au niveau 0, cette variable se développe en True ; aux niveaux 1 et supérieurs, elle se développe en False.

  • Numéros de ligne du code source : aux niveaux 0, 1 et 2, les numéros de ligne du code source sont stockés avec le bytecode afin que les exceptions puissent indiquer le numéro de ligne où elles se sont produites ; aux niveaux 3 et supérieurs, les numéros de ligne ne sont pas stockés.

Le niveau d’optimisation par défaut est généralement le niveau 0.

micropython.alloc_emergency_exception_buf(size: int) None

Alloue size octets de RAM pour le tampon d’exception d’urgence (une bonne taille se situe autour de 100 octets). Le tampon sert à créer des exceptions dans les cas où l’allocation normale de RAM échouerait (par exemple à l’intérieur d’un gestionnaire d’interruption) et à fournir ainsi des informations de traçage utiles dans ces situations.

Une bonne façon d’utiliser cette fonction est de la placer au début de votre script principal (par exemple boot.py ou main.py) ; le tampon d’exception d’urgence sera alors actif pour tout le code qui le suit.

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

Affiche des informations sur la mémoire actuellement utilisée. Si l’argument verbose est fourni, des informations supplémentaires sont affichées.

Les informations affichées dépendent de l’implémentation, mais incluent actuellement la quantité de pile et de tas utilisée. En mode verbeux, elle affiche l’intégralité du tas en indiquant quels blocs sont utilisés et lesquels sont libres.

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

Affiche des informations sur les chaînes actuellement internalisées. Si l’argument verbose est fourni, des informations supplémentaires sont affichées.

Les informations affichées dépendent de l’implémentation, mais incluent actuellement le nombre de chaînes internalisées et la quantité de RAM qu’elles utilisent. En mode verbeux, elle affiche les noms de toutes les chaînes internalisées en RAM.

micropython.stack_use() int

Renvoie un entier représentant la quantité de pile actuellement utilisée. Sa valeur absolue n’est pas particulièrement utile ; elle doit plutôt servir à calculer les différences d’utilisation de la pile en différents points.

micropython.heap_lock() None

Verrouille le tas. Tant qu’il est verrouillé, aucune allocation de mémoire ne peut avoir lieu et une MemoryError sera levée si une allocation de tas est tentée.

Les verrous s’imbriquent : appeler heap_lock() plusieurs fois augmente la profondeur de verrouillage. Le tas reste verrouillé jusqu’à ce que heap_unlock() ait été appelé le même nombre de fois.

Si le REPL devient actif alors que le tas est verrouillé, celui-ci sera déverrouillé de force.

micropython.heap_unlock() int

Décrémente la profondeur de verrouillage du tas de un et renvoie la nouvelle profondeur sous forme d’entier non négatif. Une valeur de retour de 0 signifie que le tas n’est plus verrouillé et que les allocations sont à nouveau permises.

micropython.heap_locked() int

Renvoie la profondeur de verrouillage actuelle du tas sous forme d’entier non négatif ; 0 signifie que le tas n’est pas verrouillé.

Remarque : cette fonction n’est pas disponible sur l’OpenMV Cam.

micropython.kbd_intr(chr: int) None

Définit le caractère qui lèvera une exception KeyboardInterrupt. Par défaut, il est fixé à 3 pendant l’exécution du script, ce qui correspond à Ctrl-C. Passer -1 à cette fonction désactivera la capture de Ctrl-C, et passer 3 la rétablira.

Cette fonction peut servir à empêcher la capture de Ctrl-C sur le flux de caractères entrant généralement utilisé pour le REPL, au cas où ce flux serait utilisé à d’autres fins.

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

Planifie l’exécution de la fonction func « très bientôt ». La valeur arg est passée à la fonction comme unique argument. « Très bientôt » signifie que l’environnement d’exécution MicroPython fera de son mieux pour exécuter la fonction le plus tôt possible, étant donné qu’il essaie également d’être efficace et que les conditions suivantes sont remplies :

  • Une fonction planifiée ne préemptera jamais une autre fonction planifiée.

  • Les fonctions planifiées sont toujours exécutées « entre les opcodes », ce qui signifie que toutes les opérations Python fondamentales (comme l’ajout à une liste) sont garanties atomiques.

  • Un portage donné peut définir des « régions critiques » à l’intérieur desquelles les fonctions planifiées ne seront jamais exécutées. Des fonctions peuvent être planifiées dans une région critique, mais elles ne seront pas exécutées tant que cette région n’aura pas été quittée. Un exemple de région critique est un gestionnaire d’interruption préemptif (une IRQ).

  • À l’intérieur des fonctions en code natif, les fonctions planifiées ne sont pas appelées, à moins que le code natif n’appelle une fonction qui le fait spécifiquement.

  • Certaines fonctions, notamment poll.poll, poll.ipoll, time.sleep et time.sleep_ms (y compris les pauses de durée nulle), appelleront les fonctions planifiées.

Une utilisation de cette fonction consiste à planifier une fonction de rappel depuis une IRQ préemptive. Une telle IRQ impose des restrictions sur le code qui s’exécute dans l’IRQ (par exemple le tas peut être verrouillé), et planifier une fonction à appeler plus tard lèvera ces restrictions.

Sur les portages multithread, le comportement de la fonction planifiée dépend de l’activation ou non du verrou global de l’interpréteur (GIL) pour le portage spécifique :

  • Si le GIL est activé, la fonction peut préempter n’importe quel thread et s’exécuter dans son contexte.

  • Si le GIL est désactivé, la fonction ne préemptera que le thread principal et s’exécutera dans son contexte.

Remarque : si schedule() est appelé depuis une IRQ préemptive, lorsque l’allocation de mémoire n’est pas autorisée et que la fonction de rappel à passer à schedule() est une méthode liée, la passer directement échouera. Cela s’explique par le fait que la création d’une référence vers une méthode liée provoque une allocation de mémoire. Une solution consiste à créer une référence vers la méthode dans le constructeur de la classe et à passer cette référence à schedule(). Ceci est expliqué en détail ici documentation de référence, sous « Création d’objets Python ».

Il existe une file d’attente finie pour contenir les fonctions planifiées, et schedule() lèvera une RuntimeError si la file est pleine.

Classes

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

Fournit un tampon circulaire de taille fixe pour les octets, doté d’une interface de flux. Peut être considéré comme une variante FIFO de io.BytesIO. Les deux formes du constructeur ne diffèrent que par la manière dont le tampon sous-jacent est fourni :

  • RingIO(size) alloue le tampon sous-jacent en interne. L’algorithme classique du tampon circulaire réserve un octet pour le suivi, de sorte que le tampon alloué est plus grand de un octet que size et que l’instance peut contenir les size octets de données complets. Par exemple, RingIO(16) alloue un tampon de 17 octets et contient 16 octets de données.

  • RingIO(buffer) utilise le buffer fourni sur place plutôt que d’en allouer un. Comme un octet est réservé pour le suivi, l’instance peut contenir len(buffer) - 1 octets de données. Par exemple, RingIO(bytearray(16)) contient 15 octets de données.

Une instance RingIO est sûre vis-à-vis des IRQ et des threads lorsqu’elle est utilisée pour transmettre des données dans une seule direction (par exemple écrite depuis une IRQ et lue depuis une fonction hors IRQ, ou inversement). Cela ne tient pas si une même instance est écrite à la fois depuis des contextes IRQ et hors IRQ, ce qui provoquerait souvent une corruption des données.

any() int

Renvoie un entier comptant le nombre de caractères pouvant être lus.

read(nbytes: int | None = None) bytes

Lit les caractères disponibles. Il s’agit d’une fonction non bloquante. Si nbytes est spécifié, lit au plus ce nombre d’octets, sinon lit autant de données que possible.

Valeur de retour : un objet bytes contenant les octets lus. Ce sera un objet bytes de longueur nulle si aucune donnée n’est disponible.

readline(nbytes: int | None = None) bytes

Lit une ligne se terminant par un caractère de nouvelle ligne ou retour s’il en existe un dans le tampon, sinon renvoie les octets disponibles dans le tampon. Si nbytes est spécifié, lit au plus ce nombre d’octets.

Valeur de retour : un objet bytes contenant la ligne lue.

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

Lit les octets disponibles dans le buf fourni. Si nbytes est spécifié, lit au plus ce nombre d’octets. Sinon, lit au plus len(buf) octets.

Valeur de retour : nombre entier d’octets lus dans buf.

write(buf: bytes | bytearray | memoryview) int

Écriture non bloquante d’octets depuis buf dans le tampon circulaire, limitée par l’espace disponible dans le tampon circulaire.

Valeur de retour : nombre entier d’octets écrits.

close() None

Opération sans effet fournie dans le cadre de l’interface stream standard. N’a aucun effet sur les données du tampon circulaire.