Python
micropython

MicroPython と CPython の違い

More than 1 year has passed since last update.

MicroPython と CPython の違い

※ MicroPython Wiki のDifferences to CPythonをざっと訳してみたものです。訳の質は保証しません。

MicroPython は Python 標準ライブラリのすべてをサポートしていない。除外したモジュールは、組込コントローラでの利用に不適切としたものである。メモリの消費量が多い(sqlite3など)または必要なハードウェア機能が不足している(multiprocessingなど)ため、マイクロコントローラで実装できないモジュールがある。Python の標準ライブラリの完全なリストは、ここで見つけることができる: Python 3.4 標準 lib

CPython3 (Python3 言語のリファレンス実装)と MicroPython にはいくつかの違いがある。違いは3つのカテゴリに分類される。
各カテゴリに分類される項目が変更される可能性については、カテゴリごとに異なるステータスを持つ。

デザインの相違

MicroPython は、制約の厳しい環境、特に CPython3 が実行される「デスクトップ」システムよりも性能とメモリの制約が厳しいマイクロコントローラを対象としてる。つまり、MicroPython は、この制約された環境を念頭に置いて設計しなければならず、ターゲットシステムに適合しない、またはスケールしない機能については除外する必要がある。「デザイン」の相違を変更することはまずない。

  1. MicroPython には、モジュールの広範な標準ライブラリが付属していない。完全な CPython3 ライブラリを提供することは不可能であり、理にかなっていない。多くのモジュールは、組込みシステムのコンテキストでは使用できず、また有用でもない。小さなデバイスにライブラリ全体を展開するのに十分なメモリもない。したがって、MicroPython は最小限のアプローチをとる。コアデータ型(+特定のハードウェアに固有のモジュール)だけがインタプリタに含まれ、残りの部分は特定のユーザアプリケーションのサードパーティ依存とする。micropython-lib プロジェクトが、MicroPython ための非モノリシック標準ライブラリを提供している(フォーラム)

  2. 参照カウントを使用する CPython3 とは異なり、MicroPython はメモリ管理の主な手段としてガベージコレクションを使う。

  3. MicroPython は完全な CPython オブジェクトデータモデルを実装するのではなく、そのサブセットのみを実装する。多重継承の高度な使用法である __new__ メソッドは動作しない可能性がある。メソッドの解決順序が異なる(#525)。メタクラスは(少なくともまだ)サポートしていない。

  4. MicroPython の設計はデスクリプタオブジェクトに基づいていない。これまでのところ、明示的なデスクリプタを除けば、すべてのネイティブな Python 機能(プロパティなども)を実装できている。デスクリプタは「動的すぎる」機能とみなしていて、高速かつ効率的であるという目的と矛盾している。ただし、オプトイン機能として、ディスクリプタの簡略化されたサポートを実装した。

  5. MicroPython は「マイクロ」であるため、機能や特定の関数やクラスのパラメータのサブセットのみを実装してる。それぞれの特定の問題は「実装の相違」として扱い、解決されるかもしれないが、CPython の機能を100%カバーすることはまずない。

  6. MicroPython は「マイクロ」であるため、イントロスペクションとリフレクション機能(オブジェクト名、ドキュメントストリングなど)の最小限のサブセットのみをサポートする。それぞれの特定の機能は実装の違いとして扱われ、解決されるかもしれないが、CPythonの機能を100%カバーすることはまずない。

  7. print() 関数は CPython が扱えている再帰的なデータ構造をチェックしない。しかし、スタックの使用状況をチェックするので、再帰的なデータ構造を表示してもスタックオーバーフローでクラッシュすることはない。再帰的なデータ構造についての CPython のような処理を Python アプリケーションレベルで実装することは可能である。参照する各オブジェクトの履歴を保持する関数を作成し、組み込みの print() をカスタム関数でオーバーライドする。そのような実装ではもちろん、多くのメモリを使用する可能性がある。そのため、MicroPython レベルでは実装しない。

  8. MicroPython はローカル変数の処理を最適化しており、イントロスペクション情報を記録したり提供したりしない。例えば、locals() にはローカル変数のエントリがない。

実装の相違

いくつかの機能は、制約のあるシステムに対応していなかったり、効率的に実装するのが容易でなかったりする。そのような機能は「実装の相違」としていて、一部は将来の開発の対象となる可能性がある(対応する議論と検討の後)。「実装の相違」の多くは、MicroPython 実装のサイズと性能に影響するため、MicroPython のターゲットにより特定の機能を実装しないこともある。

  1. Unicodeのサポートは作業中。これは、UTF-8を使用した内部表現に基づいている。\xNN、\uNNNN、\U000NNNNN 形式の Unicode エスケープを含む文字列は完全にサポートしている。\N{...}はサポートしていない。#695

  2. オブジェクトのファイナライズ(__del__() メソッド)は、組込み型でサポートしていないが、ユーザークラスではサポートしている。これは #245 で対応中。

  3. 組込み型のサブクラス化は部分的に実装されているが、CPython とはさまざまな相違点や互換性の問題がある。#401

  4. バッファリングされた I/O ストリーム(io.TextIOWrapper とそのスーパークラス)はサポートしていない。

  5. async def キーワードは、次のように単純化して実装されている: 別個の "coroutine" オブジェクト型はなく、async def は、その関数本体に現れる "yield" または "yield from" についての要求がないジェネレータ関数を定義するだけである。async def 関数内の "yield" または "yield from" 利用を検出したり禁止したりはしない。

  6. async with は PEP492 の記述と同等であるはず。

  7. async for は PEP492 の記述と同等であるはず。

  8. __await__ メソッドでの "Future-like objects" のサポートはない。await はコルーチンとジェネレータ("Future-like objects" ではない)の上でのみ利用できる。これは単に "yield from" の構文糖でもあり、CPython では許されない iterables と iterators を受け入れる。

  9. インスタンス __dict__ のサポートはオプションであり(多くの移植では無効化)、読取り専用なので、foo.__dict__['bar'] = 23 または foo.__dict__.update({'bar': 23}) は動作しない。#1757, #2139

既知の問題

既知の問題は本質的に、バグや誤った機能のようなものとみなされたものであり、修正される予定である。したがって、ここに書いてあるものについては、理想的にバグチケットの参照もするべきである。しかし、これらの既知の問題は、特に幅広い開発プロセスの中では、異なる優先順位を持つことに注意。したがって、実際に問題の影響を受けている場合には、計画への反映に役立てるために、ケースの詳細をチケットに追加してほしい(チケットがまだ存在しない場合は登録)。パッチの送信はさらに生産的である。(実装されていないモジュール/クラスのリストには、実装することが非常に重要と考えられるものだけが含まれていることに注意; 先述のとおり、MicroPython は一般的な完全標準ライブラリを提供していない。

  1. 関数によっては引数のチェックが十分に行われないため、間違った引数の型が渡された場合にクラッシュする可能性がある。

  2. 一部の機能が引数のチェックに assert() を使っている。間違った引数の型が渡る→誤った条件に直面すると、クラッシュにつながる。これは、Python の例外発生に置き換えること。

  3. 組み込み関数を一般的な方法でオーバーライドできない。これまでのところ、"builtins" モジュールは実装されていないので、すべてのオーバーライドは現在のモジュール内でのみ動作する。#959

  4. 永続的なバイトコードサポート(.pyc のアナログ)はベータ版である。

  5. print() 関数は Python ストリームインフラストラクチャを使用せず、基礎となる C の printf() 関数を直接使用する。つまり、sys.stdout をオーバーライドしても、print() は影響を受けない。#209

  6. 現在、 sys.stdin, sys.stdout, sys.stderr をオーバーライドすることはできない(効率化のために、これらは読み取り専用メモリに格納されている)。

  7. パッケージ/モジュールインポートのより高度な利用は、まだ完全には実装されていない。#298

  8. ジェネレータによる例外処理は完全には実装していない。 (いくつかの小さな詳細はまだ対応する必要があるかもしれない。) #243

  9. str.format() は高度な/あいまいな機能を見逃しているかもしれない
    (しかしほとんど完全に実装されている)。#407, #574

  10. % の文字列フォーマット演算子は、より高度な機能を見逃している可能性 #403, #574

  11. struct モジュール実装(ustruct という名前)は、すべての基本的な機能を持っているはずであるが、(型文字列の繰返し指定のような)いくつかの構文糖がない。Python のレベルで機能する完全な struct 機能とは名前を変えている

  12. re モジュールの代わり、最小限化した "ure" モジュールは re で提供される機能のサブセットである。micropython-lib には、"unix" 移植のために "PCRE" エンジンをベースにした完全な実装を提供している #13

  13. これまでのところ io モジュールとクラス階層の始まりだけがある。

  14. collections.deque クラスは実装していない。

  15. memoryview オブジェクトは実装していない。

  16. コンテナのスライスの割当て/削除は部分的にしか実装していない。 #509

  17. 3引数のスライシングは部分的にしか実装していない。

  18. キーワードとキーワードのみの引数は、より多くの作業が必要。 #466, #524

  19. __new__ メソッドについては基本的なサポートだけが利用できる #606, #622

  20. long intのビット演算は、部分的にのみ実装している
    (符号あり32ビット値を符号なしにキャストする作業のためのx&0xffffffff イディオム)。
    #1810