MicroPython 対話型インタープリタモード(別名 REPL)¶
このセクションでは、MicroPython 対話型インタープリタモードのいくつかの特徴について説明します。これは一般に REPL(read-eval-print-loop、読み取り・評価・出力ループ)と呼ばれており、本書ではこの対話型プロンプトを指す用語として使用します。
注釈
OpenMV Cam はこの REPL を USB シリアル(CDC)ポート経由で公開します。これはシリアルターミナルエミュレータ(または MicroPython リモートコントロール: mpremote などのツール)でカメラに直接接続する場合にのみ関係します。OpenMV IDE は REPL を使用しません — スクリプトの実行、ファイルの転送、フレームバッファのストリーミングには、別個のデバッグプロトコルを介してカメラと通信します。このページで説明する内容はすべて、直接のターミナルセッションにのみ適用されます。
自動インデント¶
コロンで終わる Python 文(たとえば if、for、while)を入力すると、プロンプトが 3 つのドット(...)に変わり、カーソルが 4 スペース分インデントされます。Enter を押すと、通常の文では同じインデントレベルで次の行が続き、適切な場合にはさらに 1 段階インデントが追加されます。Backspace キーを押すと、インデントが 1 段階解除されます。
カーソルが行頭まで戻った状態で Enter を押すと、それまでに入力したコードが実行されます。次の例は、for 文を入力した後に表示される内容を示しています(アンダースコアはカーソルが最終的にどこに来るかを示します):
>>> for i in range(30):
... _
続けて if 文を入力すると、さらに 1 段階のインデントが追加されます:
>>> for i in range(30):
... if i > 3:
... _
次に break を入力して Enter を押し、Backspace を押します:
>>> for i in range(30):
... if i > 3:
... break
... _
最後に print(i) と入力し、Enter を押し、Backspace を押してから、もう一度 Enter を押します:
>>> for i in range(30):
... if i > 3:
... break
... print(i)
...
0
1
2
3
>>>
直前の 2 行がすべてスペースだった場合は、自動インデントは適用されません。これは、複合文の入力を Enter を 2 回押すことで終了でき、3 回目の押下で入力を完了して実行できることを意味します。
自動補完¶
REPL でコマンドを入力している際に、ここまで入力した行が何かの名前の先頭に一致する場合、TAB を押すと入力可能な候補が表示されます。たとえば、まず import machine と入力して Enter を押し、machine モジュールをインポートします。次に m と入力して TAB を押すと、machine に展開されるはずです。ドット . を入力してもう一度 TAB を押します。すると、次のような表示が見られるはずです:
>>> machine.
__name__ info unique_id reset
bootloader freq rng idle
sleep deepsleep disable_irq enable_irq
Pin
候補が複数存在するようになるまで、単語は可能な限り展開されます。たとえば machine.Pin.PULL と入力して TAB を押すと machine.Pin.PULL_ に展開されます。もう一度 TAB を押すと、展開候補が表示されます:
>>> machine.Pin.PULL_
PULL_DOWN PULL_UP
>>> machine.Pin.PULL_
実行中のプログラムの中断¶
Ctrl-C を押すことで、実行中のプログラムを中断できます。これにより KeyboardInterrupt が発生し、REPL に戻ります。ただし、プログラムが KeyboardInterrupt 例外をインターセプトしていない場合に限ります。
例:
>>> for i in range(1000000):
... print(i)
...
0
1
2
3
...
6466
6467
6468
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
KeyboardInterrupt:
>>>
ペーストモード¶
ターミナルウィンドウにコードを貼り付けたい場合、自動インデント機能が処理を乱します。たとえば、次のような Python コードがあったとします:
def foo():
print('This is a test to show paste mode')
print('Here is a second line')
foo()
これを通常の REPL に貼り付けようとすると、次のような表示になります:
>>> def foo():
... print('This is a test to show paste mode')
... print('Here is a second line')
... foo()
...
Traceback (most recent call last):
File "<stdin>", line 3
IndentationError: unexpected indent
Ctrl-E を押すとペーストモードに入ります。これは本質的に自動インデント機能をオフにし、プロンプトを >>> から === に変更します。例:
>>>
paste mode; Ctrl-C to cancel, Ctrl-D to finish
=== def foo():
=== print('This is a test to show paste mode')
=== print('Here is a second line')
=== foo()
===
This is a test to show paste mode
Here is a second line
>>>
ペーストモードでは空行を貼り付けることができます。貼り付けたテキストは、ファイルであるかのようにコンパイルされます。Ctrl-D を押すとペーストモードを終了し、コンパイルを開始します。
ソフトリセット¶
ソフトリセット は Python インタープリタをリセットしますが、OpenMV Cam に接続している方式(USB)はリセットしないようにします。
REPL からは Ctrl-D を押すことで、または Python コードからは次を実行することで、ソフトリセットを実行できます:
machine.soft_reset()
たとえば、OpenMV Cam をリセットして dir() コマンドを実行すると、次のような表示になります:
>>> dir()
['__name__']
次に、いくつかの変数を作成して dir() コマンドを繰り返します:
>>> i = 1
>>> j = 23
>>> x = 'abc'
>>> dir()
['j', 'x', '__name__', 'i']
>>>
ここで Ctrl-D を入力して dir() コマンドを繰り返すと、変数がもう存在しないことがわかります:
MPY: sync filesystems
MPY: soft reboot
MicroPython v1.25.0 on 2025-05-15; OpenMV Cam H7 with STM32H743
Type "help()" for more information.
>>> dir()
['__name__']
>>>
リセットの種類と起動プロセスの詳細については、リセットとブートシーケンス を参照してください。
特殊変数 _(アンダースコア)¶
REPL を使用すると、計算を実行してその結果を確認できます。MicroPython は直前の文の結果を変数 _(アンダースコア)に格納します。そのため、アンダースコアを使って結果を変数に保存できます。例:
>>> 1 + 2 + 3 + 4 + 5
15
>>> x = _
>>> x
15
>>>
raw モードと raw-paste モード¶
raw モード(raw REPL とも呼ばれます)は、通常は人が使うものではありません。プログラムによる使用を意図しており、本質的にはエコーをオフにしたペーストモードのように動作し、オプションでフロー制御も行います。
raw モードには Ctrl-A を使って入ります。続いて Python コードを送信し、その後に Ctrl-D を送ります。Ctrl-D は「OK」で確認され、その後 Python コードがコンパイルされて実行されます。出力(またはエラー)はすべて返送されます。Ctrl-B を入力すると raw モードを終了し、通常の(別名フレンドリーな)REPL に戻ります。
raw-paste モードは raw REPL 内の追加モードであり、フロー制御を含み、コードを受信しながらコンパイルします。これにより、デバイスへの高速なコード転送に対してより堅牢になります。また、コンパイル前にコードの全コピーを保存する必要がない(標準の raw モードとは異なり)ため、受信時に使用する RAM も少なくて済みます。
raw-paste モードは次のプロトコルを使用します:
通常どおり ctrl-A を使って raw REPL に入ります。
3 バイトを書き込みます:
b"\x05A\x01"(つまり ctrl-E、続いて「A」、続いて ctrl-A)。2 バイトを読み取り、デバイスが raw-paste モードに入ったかどうかを判断します:
結果が
b"R\x00"の場合、デバイスはコマンドを理解していますが、raw paste をサポートしていません。結果が
b"R\x01"の場合、デバイスは raw paste をサポートしており、このモードに入っています。それ以外の場合、結果は
b"ra"であるはずで、デバイスは raw paste をサポートしていません。この場合、文字列b"w REPL; CTRL-B to exit\r\n>"を読み取って破棄する必要があります。
デバイスが raw-paste モードである場合は続行し、そうでない場合は標準の raw モードにフォールバックします。
2 バイトを読み取ります。これは 16 ビット符号なしリトルエンディアン整数として格納されたフロー制御のウィンドウサイズ増分(バイト単位)です。残りウィンドウサイズ変数の初期値は、この数値に設定する必要があります。
コードをデバイスに書き出します:
送信すべきバイトがある間は、残りウィンドウサイズ分までのバイトを書き込み、書き込んだバイト数だけ残りウィンドウサイズを減らします。
残りウィンドウサイズが 0 であるか、読み取り待ちのバイトがある場合は、1 バイトを読み取ります。このバイトが
b"\x01"の場合は、ステップ 5 のウィンドウサイズ増分だけ残りウィンドウサイズを増やします。このバイトがb"\x04"の場合は、デバイスがデータ受信の終了を望んでいるため、b"\x04"をデバイスに書き込み、その後はコードを送信しません。(注意:デバイスから読み取り待ちのバイトがある場合でも、それを直ちに読み取って処理する必要はありません。残りウィンドウサイズが 0 より大きい限り、デバイスは入ってくるバイトを消費し続けます。)
すべてのコードをデバイスに書き込んだら、
b"\x04"を書き込んでデータの終了を示します。b"\x04"を受信するまでデバイスから読み取ります。この時点で、デバイスは送信されたすべてのコードを受信してコンパイルし、それを実行しています。デバイスは、実行中のコードが生成した文字をすべて出力します。コードが終了すると(終了した場合)、
b"\x04"が出力され、続いて捕捉されなかった例外が出力され、さらに再びb"\x04"が出力されます。その後、標準の raw REPL に戻り、b">"を出力します。
たとえば、通常の(フレンドリーな)REPL の新しい行から始めて、次のように書き込むと:
b"\x01\x05A\x01print(123)\x04"
デバイスは次のような応答を返します:
b"\r\nraw REPL; CTRL-B to exit\r\n>R\x01\x80\x00\x01\x04123\r\n\x04\x04>"
時間経過で分解すると、これは次のようになります:
# Step 1: enter raw REPL
write: b"\x01"
read: b"\r\nraw REPL; CTRL-B to exit\r\n>"
# Step 2-5: enter raw-paste mode
write: b"\x05A\x01"
read: b"R\x01\x80\x00\x01"
# Step 6-8: write out code
write: b"print(123)\x04"
read: b"\x04"
# Step 9: code executes and result is read
read: b"123\r\n\x04\x04>"
この場合、フロー制御のウィンドウサイズ増分は 128 であり、開始時点では即座に 2 ウィンドウ分のデータが利用可能です。1 つは初期のウィンドウサイズ増分の値によるもの、もう 1 つは送信される明示的な b"\x01" の値によるものです。つまり、待機したり追加の入力フロー制御文字を確認したりする前に、最初に最大 256 バイトまで書き込めるということです。
MicroPython リモートコントロール: mpremote ツールは、OpenMV Cam 上で Python コードを実行するために、raw-paste モードを含む raw REPL を使用します。