micropython — доступ к внутренним механизмам MicroPython и управление ими

Функции

micropython.const(expr: int) int

Используется для объявления того, что выражение является константой, чтобы компилятор мог его оптимизировать. Эту функцию следует использовать следующим образом:

from micropython import const

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

Объявленные таким образом константы по-прежнему доступны как глобальные переменные за пределами модуля, в котором они объявлены. С другой стороны, если имя константы начинается с подчёркивания, то она скрыта, недоступна как глобальная переменная и не занимает память во время выполнения.

Эта функция const распознаётся непосредственно парсером MicroPython и предоставляется как часть модуля micropython главным образом для того, чтобы можно было писать скрипты, работающие как под CPython, так и под MicroPython, следуя приведённому выше шаблону.

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

Если задан level, то эта функция устанавливает уровень оптимизации для последующей компиляции скриптов и возвращает None. В противном случае она возвращает текущий уровень оптимизации.

Уровень оптимизации управляет следующими функциями компиляции:

  • Утверждения (assertions): на уровне 0 операторы assert включены и компилируются в байт-код; на уровнях 1 и выше утверждения не компилируются.

  • Встроенная переменная __debug__: на уровне 0 эта переменная разворачивается в True; на уровнях 1 и выше она разворачивается в False.

  • Номера строк исходного кода: на уровнях 0, 1 и 2 номера строк исходного кода сохраняются вместе с байт-кодом, чтобы исключения могли сообщать номер строки, в которой они произошли; на уровнях 3 и выше номера строк не сохраняются.

Уровень оптимизации по умолчанию обычно равен 0.

micropython.alloc_emergency_exception_buf(size: int) None

Выделяет size байт ОЗУ для аварийного буфера исключений (хороший размер – около 100 байт). Буфер используется для создания исключений в случаях, когда обычное выделение ОЗУ завершилось бы неудачей (например, внутри обработчика прерывания), и таким образом предоставляет полезную информацию трассировки в этих ситуациях.

Хороший способ использовать эту функцию – разместить её в начале основного скрипта (например, boot.py или main.py), и тогда аварийный буфер исключений будет активен для всего следующего за ним кода.

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

Выводит информацию о текущей используемой памяти. Если задан аргумент verbose, то выводится дополнительная информация.

Выводимая информация зависит от реализации, но в настоящее время включает объём используемого стека и кучи. В подробном режиме выводится вся куча с указанием того, какие блоки используются, а какие свободны.

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

Выводит информацию о текущих интернированных строках. Если задан аргумент verbose, то выводится дополнительная информация.

Выводимая информация зависит от реализации, но в настоящее время включает количество интернированных строк и объём используемого ими ОЗУ. В подробном режиме выводятся имена всех строк, интернированных в ОЗУ.

micropython.stack_use() int

Возвращает целое число, представляющее текущий объём используемого стека. Его абсолютное значение не особенно полезно; вместо этого его следует использовать для вычисления разницы в использовании стека в разных точках.

micropython.heap_lock() None

Блокирует кучу. Пока куча заблокирована, выделение памяти невозможно, и при любой попытке выделения памяти из кучи будет вызвано MemoryError.

Блокировки вкладываются: многократный вызов heap_lock() увеличивает глубину блокировки. Куча остаётся заблокированной до тех пор, пока heap_unlock() не будет вызван такое же количество раз.

Если REPL становится активным при заблокированной куче, то она будет принудительно разблокирована.

micropython.heap_unlock() int

Уменьшает глубину блокировки кучи на единицу и возвращает новую глубину в виде неотрицательного целого числа. Возвращаемое значение 0 означает, что куча больше не заблокирована и выделение памяти снова разрешено.

micropython.heap_locked() int

Возвращает текущую глубину блокировки кучи в виде неотрицательного целого числа; 0 означает, что куча не заблокирована.

Примечание: эта функция недоступна на OpenMV Cam.

micropython.kbd_intr(chr: int) None

Устанавливает символ, который будет вызывать исключение KeyboardInterrupt. По умолчанию во время выполнения скрипта он равен 3, что соответствует Ctrl-C. Передача -1 в эту функцию отключит перехват Ctrl-C, а передача 3 восстановит его.

Эту функцию можно использовать для предотвращения перехвата Ctrl-C во входящем потоке символов, который обычно используется для REPL, на случай, если этот поток используется для других целей.

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

Планирует выполнение функции func «очень скоро». Функции передаётся значение arg в качестве её единственного аргумента. «Очень скоро» означает, что среда выполнения MicroPython сделает всё возможное, чтобы выполнить функцию в кратчайшее возможное время, учитывая, что она также стремится быть эффективной и что выполняются следующие условия:

  • Запланированная функция никогда не вытесняет другую запланированную функцию.

  • Запланированные функции всегда выполняются «между опкодами», что означает, что все базовые операции Python (такие как добавление элемента в список) гарантированно атомарны.

  • Конкретный порт может определять «критические области», внутри которых запланированные функции никогда не будут выполняться. Функции могут быть запланированы внутри критической области, но они не будут выполнены до выхода из этой области. Примером критической области является вытесняющий обработчик прерывания (IRQ).

  • Внутри функций нативного кода запланированные функции не вызываются, если только нативный код не вызывает функцию, которая специально это делает.

  • Некоторые функции, включая poll.poll, poll.ipoll, time.sleep и time.sleep_ms (включая задержки нулевой длительности), вызывают запланированные функции.

Эту функцию можно использовать для планирования функции обратного вызова из вытесняющего IRQ. Такой IRQ накладывает ограничения на код, выполняемый в IRQ (например, куча может быть заблокирована), а планирование функции для последующего вызова снимает эти ограничения.

На многопоточных портах поведение запланированной функции зависит от того, включена ли глобальная блокировка интерпретатора (GIL) для конкретного порта:

  • Если GIL включён, функция может вытеснить любой поток и выполниться в его контексте.

  • Если GIL отключён, функция вытеснит только основной поток и выполнится в его контексте.

Примечание: если schedule() вызывается из вытесняющего IRQ, когда выделение памяти не разрешено, а функция обратного вызова, передаваемая в schedule(), является связанным методом, прямая её передача завершится неудачей. Это происходит потому, что создание ссылки на связанный метод вызывает выделение памяти. Решение состоит в том, чтобы создать ссылку на метод в конструкторе класса и передать эту ссылку в schedule(). Это подробно обсуждается здесь, в справочной документации, в разделе «Creation of Python objects».

Существует конечная очередь для хранения запланированных функций, и schedule() вызовет RuntimeError, если очередь заполнена.

Классы

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

Предоставляет кольцевой буфер фиксированного размера для байтов с потоковым интерфейсом. Его можно рассматривать как вариант FIFO-очереди для io.BytesIO. Две формы конструктора различаются только тем, как предоставляется резервный буфер:

  • RingIO(size) выделяет резервный буфер внутренне. Классический алгоритм кольцевого буфера резервирует один байт для отслеживания, поэтому выделяемый буфер на один байт больше, чем size, и экземпляр может хранить полные size байт данных. Например, RingIO(16) выделяет 17-байтовый буфер и хранит 16 байт данных.

  • RingIO(buffer) использует предоставленный buffer на месте, а не выделяет новый. Поскольку один байт зарезервирован для отслеживания, экземпляр может хранить len(buffer) - 1 байт данных. Например, RingIO(bytearray(16)) хранит 15 байт данных.

Экземпляр RingIO является IRQ-/потокобезопасным при использовании для передачи данных в одном направлении (например, запись из IRQ и чтение из не-IRQ функции, или наоборот). Это не выполняется, если в один экземпляр производится запись как из IRQ, так и из не-IRQ контекстов, что часто вызывает повреждение данных.

any() int

Возвращает целое число, показывающее количество символов, которые можно прочитать.

read(nbytes: int | None = None) bytes

Читает доступные символы. Это неблокирующая функция. Если задан nbytes, то читает не более этого количества байт, иначе читает как можно больше данных.

Возвращаемое значение: объект bytes, содержащий прочитанные байты. Будет объектом bytes нулевой длины, если данные недоступны.

readline(nbytes: int | None = None) bytes

Читает строку, оканчивающуюся символом новой строки или возврата каретки, если такой есть в буфере, иначе возвращает доступные байты в буфере. Если задан nbytes, то читает не более этого количества байт.

Возвращаемое значение: объект bytes, содержащий прочитанную строку.

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

Читает доступные байты в предоставленный buf. Если задан nbytes, то читает не более этого количества байт. Иначе читает не более len(buf) байт.

Возвращаемое значение: целочисленный счётчик количества байт, прочитанных в buf.

write(buf: bytes | bytearray | memoryview) int

Неблокирующая запись байтов из buf в кольцевой буфер, ограниченная доступным местом в кольцевом буфере.

Возвращаемое значение: целочисленный счётчик записанных байт.

close() None

Пустая операция, предоставляемая как часть стандартного интерфейса stream. Не влияет на данные в кольцевом буфере.