micropython -- 访问和控制 MicroPython 内部功能

函数

micropython.const(expr)

用于声明表达式是常量,以便编译器可以对其进行优化。此函数的使用方式如下:

from micropython import const

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

以这种方式声明的常量仍然可以作为全局变量从声明它们的模块外部访问。另一方面,如果常量以下划线开头,则它是隐藏的,不可作为全局变量使用,并且在执行期间不占用任何内存。

这个 const 函数被 MicroPython 解析器直接识别,并作为 micropython 模块的一部分提供,主要是为了让脚本可以按照上述模式在 CPython 和 MicroPython 下都能运行。

micropython.opt_level([level])

如果提供了 level,则此函数设置后续脚本编译的优化级别,并返回 None。否则,它返回当前的优化级别。

优化级别控制以下编译特性:

  • 断言:在级别 0 时,断言语句被启用并编译到字节码中;在级别 1 及以上时,断言不被编译。

  • 内置 __debug__ 变量:在级别 0 时,此变量扩展为 True;在级别 1 及以上时,扩展为 False。

  • 源代码行号:在级别 0、1 和 2 时,源代码行号与字节码一起存储,以便异常可以报告它们发生的行号;在级别 3 及以上时,不存储行号。

默认优化级别通常是级别 0。

micropython.alloc_emergency_exception_buf(size)

为紧急异常缓冲区分配 size 字节的 RAM(一个合适的大小约为 100 字节)。该缓冲区用于在正常 RAM 分配失败的情况下创建异常(例如在中断处理程序中),从而在这些情况下提供有用的回溯信息。

使用此函数的好方法是将其放在主脚本(例如 boot.py 或 main.py)的开头,这样紧急异常缓冲区将对其后的所有代码有效。

micropython.mem_info([verbose])

打印有关当前使用的内存的信息。如果提供了 verbose 参数,则打印额外信息。

打印的信息取决于实现,但目前包括使用的堆栈和堆的数量。在详细模式下,它打印出整个堆,指示哪些块被使用,哪些是空闲的。

micropython.qstr_info([verbose])

打印有关当前 interned 字符串的信息。如果提供了 verbose 参数,则打印额外信息。

打印的信息取决于实现,但目前包括 interned 字符串的数量和它们使用的 RAM 数量。在详细模式下,它打印出所有 RAM-interned 字符串的名称。

micropython.stack_use()

返回一个整数,表示当前正在使用的堆栈量。这个值的绝对值不是特别有用,而是应该用来计算不同点的堆栈使用差异。

micropython.heap_lock()
micropython.heap_unlock()
micropython.heap_locked()

锁定或解锁堆。锁定时,不能发生内存分配,如果尝试任何堆分配,将引发 MemoryError。 heap_locked() 在堆当前被锁定时返回一个真值。

这些函数可以嵌套,即可以连续多次调用 heap_lock(),锁深度会增加,然后必须调用相同次数的 heap_unlock() 才能使堆再次可用。

heap_unlock() 和 heap_locked() 都返回当前的锁深度(前者在解锁后)作为非负整数,0 表示堆未被锁定。

如果 REPL 在堆被锁定的情况下变为活动状态,它将被强制解锁。

注意:heap_locked() 在大多数端口上默认未启用, 需要 MICROPY_PY_MICROPYTHON_HEAP_LOCKED。

micropython.kbd_intr(chr)

设置将引发 KeyboardInterrupt 异常的字符。默认情况下,在脚本执行期间,这被设置为 3,对应于 Ctrl-C。 向此函数传递 -1 将禁用 Ctrl-C 的捕获,传递 3 将恢复它。

此函数可用于防止在通常用于 REPL 的传入字符流上捕获 Ctrl-C,以防该流用于其他目的。

micropython.schedule(func, arg)

安排函数 func 在"很快"执行。该函数被传递值 arg 作为其唯一参数。"很快"意味着 MicroPython 运行时将尽最大努力在最早的可能时间执行该函数,前提是它也试图高效,并且满足以下条件:

  • 调度的函数永远不会抢占另一个调度的函数。

  • 调度的函数总是在"操作码之间"执行,这意味着所有基本的 Python 操作(例如附加到列表)都保证是原子的。

  • 给定的端口可能定义"关键区域",在其中永远不会执行调度的函数。函数可以在关键区域内调度,但它们不会执行,直到该区域退出。关键区域的一个例子是抢占中断处理程序(IRQ)。

此函数的一个用途是从抢占 IRQ 调度回调。 这样的 IRQ 对在 IRQ 中运行的代码施加了限制(例如堆可能被锁定),安排稍后调用的函数将解除这些限制。

在多线程端口上,调度函数的行为取决于特定端口是否启用了全局解释器锁(GIL):

  • 如果启用了 GIL,该函数可以抢占任何线程并在其上下文中运行。

  • 如果禁用了 GIL,该函数只会抢占主线程并在其上下文中运行。

注意:如果从抢占 IRQ 调用 schedule(),当内存分配不允许且要传递给 schedule() 的回调是绑定方法时,直接传递会失败。这是因为创建对绑定方法的引用会导致内存分配。解决方案是在类构造函数中创建对方法的引用,并将该引用传递给 schedule()。这在 参考文档 的"Python 对象的创建"下详细讨论。

有一个有限的队列来保存调度的函数,如果队列已满,schedule() 将引发 RuntimeError。

类

class micropython.RingIO(size)
class micropython.RingIO(buffer)

提供带有流接口的字节固定大小环形缓冲区。可以被视为 io.BytesIO 的 fifo 队列变体。

当使用整数大小创建时,将分配适当的缓冲区。 或者,可以向构造函数提供 bytearray 或类似的缓冲区协议对象以供就地使用。

使用经典的环形缓冲区算法,允许使用任何大小的缓冲区,但会消耗一个字节用于跟踪。如果使用整数大小初始化,这将被考虑在内,例如 RingIO(16) 将在内部分配一个 17 字节的缓冲区,以便它可以容纳 16 字节的数据。 但是,当传入预分配的缓冲区时,其原始长度的少一个字节将可用于存储,例如 RingIO(bytearray(16)) 只会容纳 15 字节的数据。

当 RingIO 实例用于在单一方向传递数据时,它可以是 IRQ/线程安全的,例如在 IRQ 中写入并在非 IRQ 函数中读取 (反之亦然)。如果尝试例如从 IRQ 和非 IRQ 代码写入单个实例,这将不成立,这通常会导致数据损坏。

any()

返回可以读取的字符数的整数。

read([nbytes])

读取可用字符。这是一个非阻塞函数。如果指定了 nbytes,则最多读取那么多字节,否则读取尽可能多的数据。

返回值:包含读取字节的字节对象。如果没有可用数据,将是零长度的字节对象。

readline([nbytes])

读取一行,以换行符结束或如果缓冲区中存在则返回,否则返回缓冲区中的可用字节。如果指定了 nbytes,则最多读取那么多字节。

返回值:包含读取行的字节对象。

readinto(buf[, nbytes])

读取可用字节到提供的 buf 中。如果指定了 nbytes,则最多读取那么多字节。否则,最多读取 len(buf) 字节。

返回值:读取到 buf 中的字节数的整数。

write(buf)

从 buf 非阻塞写入字节到环形缓冲区,受环形缓冲区可用空间的限制。

返回值:写入的字节数的整数。

close()

作为标准 stream 接口的一部分提供的无操作。对环形缓冲区中的数据没有影响。