MicroPython .mpy files

MicroPython defines the concept of an .mpy file which is a binary container file format that holds precompiled code, and which can be imported like a normal .py module. The file foo.mpy can be imported via import foo, as long as foo.mpy can be found in the usual way by the import machinery. Usually, each directory listed in sys.path is searched in order. When searching a particular directory foo.py is looked for first and if that is not found then foo.mpy is looked for, then the search continues in the next directory if neither is found. As such, foo.py will take precedence over foo.mpy. MicroPython定义了.mpy文件的概念,它是一个二进制容器 保存预编译代码的文件格式,并且可以像 正常. py模块。文件``foo.mpy``可以通过``import foo``导入, 只要 foo.mpy 可以通过进口机械找到。 通常,sys.path``中列出的每个目录。按顺序搜索路径。当 搜索特定目录``foo.py``首先被寻找,如果 没有被发现,那么``foo.mpy``是寻找,然后搜索继续在 如果没有找到下一个目录。因此,``foo.py``将优先 在``foo.mpy

These .mpy files can contain bytecode which is usually generated from Python source files (.py files) via the mpy-cross program. For some architectures an .mpy file can also contain native machine code, which can be generated in a variety of ways, most notably from C source code. 这些.mpy文件可以包含通常由Python生成的字节码 通过``mpy-cross``程序生成的源文件(.py文件)。对于一些架构 mpy文件还可以包含本地机器代码,这些代码可以在 有多种方法,最明显的是从C源代码。

Versioning and compatibility of .mpy files

A given .mpy file may or may not be compatible with a given MicroPython system. Compatibility is based on the following: 一个给定的.mpy文件可能与一个给定的MicroPython系统兼容,也可能不兼容。 兼容性基于以下几点:

  • Version of the .mpy file: the version of the file must match the version supported by the system loading it.

  • mpy文件的版本:文件的版本必须与版本匹配 系统支持加载它。

  • Bytecode features used in the .mpy file: there are two bytecode features which must match between the file and the system: unicode support and inline caching of map lookups in the bytecode.

  • mpy文件中使用的字节码特性:有两个字节码特性 文件和系统之间必须匹配的是:unicode支持和 字节码中映射查找的内联缓存。

  • Small integer bits: the .mpy file will require a minimum number of bits in a small integer and the system loading it must support at least this many bits.

  • 小整数位:.mpy文件将需要一个最小的二进制数 一个小整数,加载它的系统必须至少支持这么多 位。

  • Qstr compression window size: the .mpy file will require a minimum window size for qstr decompression and the system loading it must have a window greater or equal to this size.

  • Qstr压缩窗口大小:.mpy文件需要一个最小窗口 qstr解压的大小和加载它的系统必须有一个窗口 大于或等于这个大小。

  • Native architecture: if the .mpy file contains native machine code then it will specify the architecture of that machine code and the system loading it must support execution of that architecture’s code.

  • 本机架构:如果.mpy文件包含本机代码,则 它将指定机器代码和系统的架构 加载它必须支持该架构代码的执行。

If a MicroPython system supports importing .mpy files then the sys.implementation.mpy field will exist and return an integer which encodes the version (lower 8 bits), features and native architecture. 如果MicroPython系统支持导入.mpy文件,则 ``sys.implementation.mpy``字段将存在并返回一个整数 对版本(低8位)、特性和本机架构进行编码。

Trying to import an .mpy file that fails one of the first four tests will raise ValueError('incompatible .mpy file'). Trying to import an .mpy file that fails the native architecture test (if it contains native machine code) will raise ValueError('incompatible .mpy arch'). 如果导入的.mpy文件在前四个测试中失败,则会失败 引发``ValueError(‘incompatible .mpy file’)``。试图导入。mpy 未能通过本机架构测试的文件(如果它包含本机机器) 代码)将引发``ValueError(‘incompatible .mpy arch’)``。

If importing an .mpy file fails then try the following: 如果导入.mpy文件失败,请尝试以下操作:

  • Determine the .mpy version and flags supported by your MicroPython system by executing:

  • 确定MicroPython系统支持的.mpy版本和标志 通过执行:

    import sys sys_mpy = sys.implementation.mpy arch = [None, ‘x86’, ‘x64’,

    ‘armv6’, ‘armv6m’, ‘armv7m’, ‘armv7em’, ‘armv7emsp’, ‘armv7emdp’, ‘xtensa’, ‘xtensawin’][sys_mpy >> 10]

    print(‘mpy version:’, sys_mpy & 0xff) print(‘mpy flags:’, end=’’) if arch:

    print(‘ -march=’ + arch, end=’’)

    if sys_mpy & 0x100:

    print(‘ -mcache-lookup-bc’, end=’’)

    if not sys_mpy & 0x200:

    print(‘ -mno-unicode’, end=’’)

    print()

  • Check the validity of the .mpy file by inspecting the first two bytes of the file. The first byte should be an uppercase ‘M’ and the second byte will be the version number, which should match the system version from above. If it doesn’t match then rebuild the .mpy file.

  • 检查.mpy文件的前两个字节 该文件。第一个字节应该是大写的’M’,第二个字节 将是版本号,应该与上面的系统版本匹配。 如果不匹配,那么重新构建.mpy文件。

  • Check if the system .mpy version matches the version emitted by mpy-cross that was used to build the .mpy file, found by mpy-cross --version. *检查系统。mpy版本是否与``mpy-cross``发出的版本匹配 用于构建。mpy文件,通过 mpy-cross --version``找到。 If it doesn't match then recompile ``mpy-cross from the Git repository checked out at the tag (or hash) reported by mpy-cross --version. 如果不匹配,那么从Git存储库中重新编译``mpy-cross`` 在``mpy-cross –version``报告的标签(或散列)处检出。

  • Make sure you are using the correct mpy-cross flags, found by the code above, or by inspecting the MPY_CROSS_FLAGS Makefile variable for the port that you are using. *确保你使用了正确的``mpy-cross``标志,由代码发现 ,或检查``MPY_CROSS_FLAGS``的Makefile变量 您正在使用的端口。

The following table shows the correspondence between MicroPython release and .mpy version. 下表显示了MicroPython版本之间的对应关系 和.mpy版本。

MicroPython release

.mpy version

v1.12 and up

5

v1.11

4

v1.9.3 - v1.10

3

v1.9 - v1.9.2

2

v1.5.1 - v1.8.7

0

For completeness, the next table shows the Git commit of the main MicroPython repository at which the .mpy version was changed. 为了完整起见,下一个表显示了main的Git提交 MicroPython储存库,.mpy版本在其中被更改。

.mpy version change

Git commit

4 to 5

5716c5cf65e9b2cb46c2906f40302401bdd27517

3 to 4

9a5f92ea72754c01cc03e5efcdfe94021120531e

2 to 3

ff93fd4f50321c6190e1659b19e64fef3045a484

1 to 2

dd11af209d226b7d18d5148b239662e30ed60bad

0 to 1

6a11048af1d01c78bdacddadd1b72dc7ba7c6478

initial version 0

d8c834c95d506db979ec871417de90b7951edc30

Binary encoding of .mpy files mpy文件的二进制编码 —————————–

MicroPython .mpy files are a binary container format with code objects stored internally in a nested hierarchy. To keep files small while still providing a large range of possible values it uses the concept of a variably-encoded-unsigned-integer (vuint) in many places. Similar to utf-8 encoding, this encoding stores 7 bits per byte with the 8th bit (MSB) set if one or more bytes follow. The bits of the unsigned integer are stored in the vuint in LSB form. mpy文件是带有代码对象的二进制容器格式 存储在内部的嵌套层次结构中。在静止时保持文件小 提供了大量的可能值,它使用了a的概念 可变编码无符号整数(vuint)在许多地方。类似于utf-8 编码,这个编码用8位(MSB)集存储每字节7位 如果后面跟着一个或多个字节。存储无符号整数的位 在vuint的LSB形式。

The top-level of an .mpy file consists of two parts: mpy文件的顶层由两部分组成:

  • The header.

  • 标题。

  • The raw-code for the outer scope of the module.

  • 模块外部范围的原始代码。 This outer scope is executed when the .mpy file is imported. 这个外部范围在导入.mpy文件时执行。

The header 标题 ~~~~~~~~~~

The .mpy header is: mpy标题是:

size

field

byte

value 0x4d (ASCII ‘M’)

byte

.mpy version number

byte

feature flags

byte

number of bits in a small int

vuint

size of qstr window

Raw code elements 原始代码元素 ~~~~~~~~~~~~~~~~~

A raw-code element contains code, either bytecode or native machine code. Its contents are: 原始代码元素包含代码,可以是字节码,也可以是本机代码。它的 内容是:

size

field

vuint

type and size

code (bytecode or machine code)

vuint

number of constant objects

vuint

number of sub-raw-code elements

constant objects

sub-raw-code elements

The first vuint in a raw-code element encodes the type of code stored in this element (the two least-significant bits), and the decompressed length of the code (the amount of RAM to allocate for it). 原始代码元素中的第一个vuint对存储在其中的代码类型进行编码 元素(两个最小有效位)和代码的解压缩长度 (分配给它的RAM数量)。

Following the vuint comes the code itself. In the case of bytecode it also contains compressed qstr values. 追随vuint的是代码本身。在字节码的情况下,它也包含 压缩qstr值。

Following the code comes a vuint counting the number of constant objects, and another vuint counting the number of sub-raw-code elements. 代码后面是vuint计数常量对象的数量,和 另一种vuint计算亚原始码元素的数量。

The constant objects are then stored next. 然后接下来存储常量对象。

Finally any sub-raw-code elements are stored, recursively. 最后,递归地存储所有sub-raw-code元素。