MicroPython .mpy ファイル¶
MicroPython は .mpy ファイルの概念を定義しています。これはプリコンパイルされたコードを保持するバイナリコンテナファイル形式であり、通常の .py モジュールのようにインポートできます。ファイル foo.mpy
は、foo.mpy
をインポート機構が通常の方法で見つけることができる限り import foo
でインポートできます。通常 sys.path
にリストされている各ディレクトリが順番に検索されます。特定のディレクトリを検索で foo.py
が最初に検索され、それが見つからなければ foo.mpy
が検索されます。どちらも見つからない場合は次のディレクトリで検索が続行されます。そのため foo.py
は foo.mpy
に優先します。
これらの .mpy ファイルには、通常 mpy-cross
プログラムで Python ソースファイル(.py ファイル)から生成されるバイトコードを含めることができます。一部のアーキテクチャでは .mpy ファイルにネイティブマシンコードを含めることもできます。ネイティブコードはマシンコードはさまざまな方法で生成できますが、C 言語ソースコードから生成することが特に多いです。
.mpy ファイルのバージョンと互換性¶
利用しようとする .mpy ファイルは、特定の MicroPython システムと互換性がある場合と互換性がない場合があります。互換性は以下に基づいています:
- .mpy ファイルのバージョン: ファイルのバージョンは、それをロードするシステムでサポートされているバージョンと一致する必要があります。
- .mpy ファイルで使用されるバイトコード機能: ファイルとシステムの間で一致する必要がある2つのバイトコード機能があります。ユニコードサポートとバイトコードでのマップ検索のインラインキャッシュです。
- スモール整数ビット: .mpy ファイルにはスモール整数の最小ビット数の要求があり、.mpy をロードするシステムは少なくともこの数のビットをサポートする必要があります。
- qstr 圧縮ウィンドウサイズ: .mpy ファイルには qstr 解凍のための最小ウィンドウサイズの要求があり、.mpy をロードするシステムにはこのサイズ以上のウィンドウが必要です。
- ネイティブアーキテクチャ: .mpyファイルにネイティブマシンコードが含まれている場合、そのマシンコードのアーキテクチャの指定があり、.mpy をロードするシステムはそのアーキテクチャのコードの実行をサポートする必要があります。
MicroPython システムが .mpy ファイルのインポートをサポートしている場合には、 sys.implementation.mpy
フィールドが存在し、バージョン(下位8ビット)、機能、ネイティブアーキテクチャをエンコードした整数を返します。
最初の4つのテストの1つに失敗した .mpy ファイルをインポートしようとすると ValueError('incompatible .mpy file')
が発生します。(ネイティブマシンコードが含まれている場合)ネイティブアーキテクチャのテストに失敗した .mpy ファイルをインポートしようとすると ValueError('incompatible .mpy arch')
が発生します。
.mpy ファイルのインポートに失敗した場合は、次を試してください:
以下を実行して、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()
ファイルの先頭2バイトを調べて、.mpy ファイルの妥当性を確認します。先頭バイトは大文字の 'M' で、2バイト目はバージョン番号です。このバージョン番号は、上記のシステムバージョンと一致する必要があります。一致しない場合は .mpy ファイルを再作成してください。
.mpy ファイルを作成するのに使った
mpy-cross
の出した .mpy バーションがシステムの .mpy バージョンと一致するかを確認します。mpy-cross
の出すバージョンはmpy-cross --version
でわかります。一致しない場合はmpy-cross --version
によって報告されたタグ(またはハッシュ)でチェックアウトした Git リポジトリにあるmpy-cross
で再コンパイルします。mpy-cross
フラグが正しいかを確認します。フラグは上記のコードで見つけるか、使っているポートのMPY_CROSS_FLAGS
Makefile 変数を調べてください。
次の表は、MicroPythonリリースと.mpyバージョンの対応を示しています。
MicroPython リリース | .mpy バージョン |
---|---|
v1.12 以上 | 5 |
v1.11 | 4 |
v1.9.3 - v1.10 | 3 |
v1.9 - v1.9.2 | 2 |
v1.5.1 - v1.8.7 | 0 |
完全を期すため、次の表は .mpy バージョンが変更されたメイン MicroPython リポジトリの Git コミットを示しています。
.mpy バージョン変更 | Git コミット |
---|---|
4 から 5 | 5716c5cf65e9b2cb46c2906f40302401bdd27517 |
3 から 4 | 9a5f92ea72754c01cc03e5efcdfe94021120531e |
2 から 3 | ff93fd4f50321c6190e1659b19e64fef3045a484 |
1 から 2 | dd11af209d226b7d18d5148b239662e30ed60bad |
0 から 1 | 6a11048af1d01c78bdacddadd1b72dc7ba7c6478 |
初期バージョン 0 | d8c834c95d506db979ec871417de90b7951edc30 |
.mpy ファイルのバイナリエンコーディング¶
MicroPython .mpy ファイルは、ネストされた階層内にコードオブジェクトを格納したバイナリコンテナー形式です。大きな範囲の値を提供しながらもファイルを小さく保つために、多くの場所で可変エンコード符号なし整数(variably-encoded-unsigned-integer: vuint)の概念を使用します。utf-8 エンコーディングと同様に、このエンコーディングは1バイトあたり7ビットを格納し、1つ以上のバイトが続く場合は8ビット目(MSB)が設定されます。符号なし整数のビットは、LSB 形式で vuint に格納されます。
.mpyファイルのトップレベルは2つの部分で構成されています:
- ヘッダー
- モジュールの外部スコープの raw コード。この外部スコープは .mpy ファイルがインポートされるときに実行されます。
ヘッダー¶
.mpy のヘッダーは次のとおりです:
サイズ | フォールド |
---|---|
バイト | 値 0x4d (ASCII の "M') |
バイト | .mpy バージョン番号 |
バイト | 機能フラグ |
バイト | スモール整数のビット数 |
vuint | qstr ウィンドウのサイズ |
raw コードの要素¶
raw コードの要素には、バイトコードまたはネイティブマシンコードのコードが含まれます。その内容は次のとおりです:
サイズ | フォールド |
---|---|
vuint | タイプとサイズ |
... | コード(バイトコードまたはマシンコード) |
vuint | 定数オブジェクトの数 |
vuint | 副 raw コード要素の数 |
... | 定数オブジェクト |
... | 副 raw コード要素 |
raw コード要素の最初の vuint は、この要素に格納されているコードのタイプ(最下位2ビット)と、圧縮解除されたコードの長さ(割り当てられるRAMの量)をエンコードしています。
vuint に続いてコード自体が続きます。バイトコードの場合、圧縮された qstr 値も含まれます。
コードに続いて、定数オブジェクトの数を数える vuint と、副 raw コード要素数の vuint が続きます。
定数オブジェクトは次に保存されます。
最後に 副 raw コード要素が再帰的に保存されます。