A MicroPython interaktív értelmező mód (más néven REPL)

Ez a fejezet a MicroPython interaktív értelmező mód néhány jellemzőjét ismerteti. Erre gyakran használt kifejezés a REPL (read-eval-print-loop), amelyet ennek az interaktív parancssornak a megnevezésére fogunk használni.

Megjegyzés

Az OpenMV Cam ezt a REPL-t az USB soros (CDC) portján keresztül teszi elérhetővé. Ez csak akkor releváns, ha közvetlenül egy soros terminálemulátorral (vagy egy olyan eszközzel, mint az MicroPython távoli vezérlés: mpremote) csatlakozol a kamerához. Az OpenMV IDE nem használja a REPL-t — egy külön hibakeresési protokollon keresztül kommunikál a kamerával, hogy szkripteket futtasson, fájlokat vigyen át és a framebuffert streamelje. Minden, ami ezen az oldalon szerepel, kizárólag a közvetlen terminálmunkamenetekre vonatkozik.

Automatikus behúzás

Ha kettősponttal végződő Python utasításokat gépelsz (például if, for, while), akkor a parancssor három pontra (…) változik, és a kurzor 4 szóközzel behúzódik. Amikor megnyomod az entert, a következő sor a megszokott utasítások esetében ugyanazon a behúzási szinten folytatódik, vagy ahol indokolt, egy további behúzási szinttel. Ha megnyomod a backspace billentyűt, az egy behúzási szintet visszavon.

Ha a kurzor egészen a sor elejéig visszatért, az enter megnyomása végrehajtja a beírt kódot. Az alábbi mutatja, mit látnál egy for utasítás beírása után (az aláhúzás jelzi, hol áll meg a kurzor):

>>> for i in range(30):
...     _

Ha ezután beírsz egy if utasítást, egy további behúzási szint jelenik meg:

>>> for i in range(30):
...     if i > 3:
...         _

Most írd be a break parancsot, nyomj entert, majd backspace-t:

>>> for i in range(30):
...     if i > 3:
...         break
...     _

Végül írd be a print(i) parancsot, nyomj entert, majd backspace-t, és nyomj újra entert:

>>> for i in range(30):
...     if i > 3:
...         break
...     print(i)
...
0
1
2
3
>>>

Az automatikus behúzás nem érvényesül, ha az előző két sor csupa szóköz volt. Ez azt jelenti, hogy egy összetett utasítás bevitelét két enter megnyomásával fejezheted be, a harmadik megnyomás pedig befejezi és végrehajtja.

Automatikus kiegészítés

Miközben egy parancsot gépelsz a REPL-ben, ha az eddig beírt sor megfelel valaminek a nevének elejének, a TAB megnyomása megjeleníti a lehetséges beírható elemeket. Például először importáld a machine modult az import machine beírásával és az enter megnyomásával. Ezután írd be, hogy m, és nyomj TAB-ot, mire machine lesz belőle. Írj be egy pontot ., és nyomj újra TAB-ot. Valami ilyesmit kell látnod:

>>> machine.
__name__        info            unique_id       reset
bootloader      freq            rng             idle
sleep           deepsleep       disable_irq     enable_irq
Pin

A szó a lehető legnagyobb mértékben kiegészül, amíg több lehetőség is létezik. Például írd be, hogy machine.Pin.PULL, és nyomj TAB-ot, mire machine.Pin.PULL_ lesz belőle. A TAB második megnyomása megjeleníti a lehetséges kiegészítéseket:

>>> machine.Pin.PULL_
PULL_DOWN       PULL_UP
>>> machine.Pin.PULL_

Futó program megszakítása

Egy futó programot a Ctrl-C megnyomásával szakíthatsz meg. Ez egy KeyboardInterrupt kivételt vált ki, amely visszahoz a REPL-be, feltéve hogy a programod nem fogja el a KeyboardInterrupt kivételt.

Például:

>>> 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:
>>>

Beillesztési mód

Ha valamilyen kódot szeretnél beilleszteni a terminálablakba, az automatikus behúzás funkció elrontja a dolgokat. Például, ha a következő Python kódod lenne:

def foo():
    print('This is a test to show paste mode')
    print('Here is a second line')
foo()

és ezt a megszokott REPL-be próbálod beilleszteni, akkor valami ilyesmit fogsz látni:

>>> 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

Ha megnyomod a Ctrl-E-t, akkor beillesztési módba lépsz, ami lényegében kikapcsolja az automatikus behúzás funkciót, és a parancssort >>> helyett === jelre változtatja. Például:

>>>
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
>>>

A beillesztési mód lehetővé teszi üres sorok beillesztését is. A beillesztett szöveg úgy fordul le, mintha fájl lenne. A Ctrl-D megnyomása kilép a beillesztési módból és elindítja a fordítást.

Szoftveres újraindítás

A Szoftveres visszaállítás újraindítja a Python értelmezőt, de igyekszik nem újraindítani azt a módot, ahogyan az OpenMV Camhez csatlakozol (USB).

Szoftveres újraindítást a REPL-ből a Ctrl-D megnyomásával végezhetsz, vagy a Python kódodból a következő végrehajtásával:

machine.soft_reset()

Például, ha újraindítod az OpenMV Camet és végrehajtasz egy dir() parancsot, valami ilyesmit látnál:

>>> dir()
['__name__']

Most hozz létre néhány változót, és ismételd meg a dir() parancsot:

>>> i = 1
>>> j = 23
>>> x = 'abc'
>>> dir()
['j', 'x', '__name__', 'i']
>>>

Most ha megnyomod a Ctrl-D-t, és megismétled a dir() parancsot, látni fogod, hogy a változóid már nem léteznek:

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__']
>>>

Az újraindítási típusokról és az indítási folyamatról bővebben lásd: Visszaállítási és indítási folyamat.

A speciális _ (aláhúzás) változó

A REPL használata közben számításokat végezhetsz és láthatod az eredményeket. A MicroPython az előző utasítás eredményét a _ (aláhúzás) változóban tárolja. Így az aláhúzás segítségével elmentheted az eredményt egy változóba. Például:

>>> 1 + 2 + 3 + 4 + 5
15
>>> x = _
>>> x
15
>>>

Nyers mód és nyers-beillesztési mód

A nyers mód (más néven nyers REPL) nem olyasmi, amit egy ember általában használna. Programozott használatra szánták, és lényegében úgy viselkedik, mint a beillesztési mód kikapcsolt visszhanggal és opcionális adatáramlás-vezérléssel.

A nyers módba a Ctrl-A megnyomásával lépsz be. Ezután elküldöd a Python kódodat, majd egy Ctrl-D-t. A Ctrl-D-t egy «OK» nyugtázza, majd a Python kód lefordul és végrehajtódik. Bármilyen kimenet (vagy hiba) visszaküldésre kerül. A Ctrl-B megnyomása kilép a nyers módból és visszatér a megszokott (más néven barátságos) REPL-hez.

A nyers-beillesztési mód a nyers REPL egy további módja, amely tartalmaz adatáramlás-vezérlést, és a kódot a fogadás közben fordítja le. Ez robusztusabbá teszi a kód nagy sebességű átvitelét az eszközre, és kevesebb RAM-ot is használ a fogadás során, mivel nem kell a kódról szó szerinti másolatot tárolnia a fordítás előtt (a szabványos nyers móddal ellentétben).

A nyers-beillesztési mód a következő protokollt használja:

  1. Lépj be a nyers REPL-be a szokásos módon a Ctrl-A segítségével.

  2. Írj ki 3 bájtot: b"\x05A\x01" (azaz Ctrl-E, majd „A”, majd Ctrl-A).

  3. Olvass be 2 bájtot annak megállapításához, hogy az eszköz belépett-e a nyers-beillesztési módba:

    • Ha az eredmény b"R\x00", akkor az eszköz érti a parancsot, de nem támogatja a nyers beillesztést.

    • Ha az eredmény b"R\x01", akkor az eszköz támogatja a nyers beillesztést, és belépett ebbe a módba.

    • Egyébként az eredménynek b"ra"-nak kell lennie, és az eszköz nem támogatja a nyers beillesztést, valamint a b"w REPL; CTRL-B to exit\r\n>" szöveget be kell olvasni és el kell vetni.

  4. Ha az eszköz nyers-beillesztési módban van, akkor folytasd, egyébként térj vissza a szabványos nyers módhoz.

  5. Olvass be 2 bájtot, ez az adatáramlás-vezérlés ablakméret-növekménye (bájtban) 16 bites előjel nélküli little endian egész számként tárolva. A fennmaradó ablakméret változó kezdőértékét erre a számra kell beállítani.

  6. Írd ki a kódot az eszközre:

    • Amíg vannak küldendő bájtok, írj ki legfeljebb a fennmaradó ablakméretnyi bájtot, és csökkentsd a fennmaradó ablakméretet a kiírt bájtok számával.

    • Ha a fennmaradó ablakméret 0, vagy van beolvasásra váró bájt, olvass be 1 bájtot. Ha ez a bájt b"\x01", akkor növeld a fennmaradó ablakméretet az 5. lépésben kapott ablakméret-növekménnyel. Ha ez a bájt b"\x04", akkor az eszköz be akarja fejezni az adatfogadást, és b"\x04"-et kell az eszközre írni, és utána több kódot nem szabad küldeni. (Megjegyzés: ha van az eszközről beolvasásra váró bájt, akkor azt nem kell azonnal beolvasni és kezelni, az eszköz mindaddig folytatja a beérkező bájtok feldolgozását, amíg a fennmaradó ablakméret nagyobb 0-nál.)

  7. Amikor az összes kód kiírásra került az eszközre, írj b"\x04"-et az adatok végének jelzésére.

  8. Olvass az eszközről, amíg b"\x04" érkezik. Ezen a ponton az eszköz megkapta és lefordította az összes elküldött kódot, és éppen végrehajtja azt.

  9. Az eszköz kiad minden karaktert, amelyet a végrehajtódó kód előállít. Amikor (ha) a kód befejeződik, b"\x04" kerül kiadásra, ezt követi minden el nem kapott kivétel, majd ismét egy b"\x04". Ezután visszatér a szabványos nyers REPL-hez, és kiadja a b">" jelet.

Például, ha a megszokott (barátságos) REPL-ben egy új sor elejéről indulva a következőt írod:

b"\x01\x05A\x01print(123)\x04"

Akkor az eszköz valami ilyesmivel válaszol:

b"\r\nraw REPL; CTRL-B to exit\r\n>R\x01\x80\x00\x01\x04123\r\n\x04\x04>"

Időben lebontva ez így néz ki:

# 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>"

Ebben az esetben az adatáramlás-vezérlés ablakméret-növekménye 128, és a kezdetkor azonnal két ablaknyi adat áll rendelkezésre, egy a kezdeti ablakméret-növekmény értékéből és egy az elküldött explicit b"\x01" értékből. Ez tehát azt jelenti, hogy kezdetben akár 256 bájt is kiírható, mielőtt további beérkező adatáramlás-vezérlő karaktereket kellene bevárni vagy ellenőrizni.

Az MicroPython távoli vezérlés: mpremote eszköz a nyers REPL-t használja, beleértve a nyers-beillesztési módot is, Python kód futtatására az OpenMV Camen.