โหมดอินเทอร์พรีเตอร์แบบโต้ตอบของ MicroPython (หรือที่รู้จักกันในชื่อ REPL)

ส่วนนี้ครอบคลุมคุณลักษณะบางประการของโหมดอินเทอร์พรีเตอร์แบบโต้ตอบของ MicroPython โดยทั่วไปมักเรียกสิ่งนี้ว่า REPL (read-eval-print-loop) ซึ่งจะใช้เรียกพรอมต์แบบโต้ตอบนี้

Note

OpenMV Cams เปิดเผย REPL นี้ผ่านพอร์ต USB serial (CDC) เกี่ยวข้องเฉพาะเมื่อคุณเชื่อมต่อกับกล้องโดยตรงด้วยโปรแกรมจำลองเทอร์มินัล serial (หรือเครื่องมือเช่น MicroPython การควบคุมระยะไกล: mpremote) OpenMV IDE ไม่ใช้ REPL — โปรแกรมสื่อสารกับกล้องผ่านโปรโตคอลดีบักแยกต่างหากเพื่อรันสคริปต์ โอนถ่ายไฟล์ และสตรีมบัฟเฟอร์เฟรม ทุกสิ่งที่อธิบายในหน้านี้ใช้ได้กับเซสชันเทอร์มินัลโดยตรงเท่านั้น

การเยื้องอัตโนมัติ

เมื่อพิมพ์คำสั่ง Python ที่ลงท้ายด้วยเครื่องหมายโคลอน (เช่น if, for, while) พรอมต์จะเปลี่ยนเป็นจุดสามจุด (...) และเคอร์เซอร์จะเยื้องเข้าไป 4 ช่องว่าง เมื่อกด Return บรรทัดถัดไปจะดำเนินการต่อในระดับการเยื้องเดิมสำหรับคำสั่งปกติ หรือเพิ่มระดับการเยื้องเพิ่มเติมตามความเหมาะสม หากกด Backspace จะยกเลิกการเยื้องหนึ่งระดับ

หากเคอร์เซอร์อยู่ที่ตำแหน่งเริ่มต้นสุด การกด RETURN จะทำให้โค้ดที่พิมพ์ไว้ถูกประมวลผล ต่อไปนี้แสดงสิ่งที่จะเห็นหลังจากพิมพ์คำสั่ง for (เครื่องหมายขีดล่างแสดงตำแหน่งที่เคอร์เซอร์จะอยู่):

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

หากพิมพ์คำสั่ง if ต่อ จะมีการเพิ่มระดับการเยื้องอีกหนึ่งระดับ:

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

ตอนนี้พิมพ์ break แล้วกด RETURN จากนั้นกด BACKSPACE:

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

สุดท้ายพิมพ์ print(i) กด RETURN กด BACKSPACE แล้วกด RETURN อีกครั้ง:

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

การเยื้องอัตโนมัติจะไม่ทำงานหากสองบรรทัดก่อนหน้าเป็นช่องว่างทั้งหมด ซึ่งหมายความว่าคุณสามารถสิ้นสุดการพิมพ์คำสั่งแบบรวมได้โดยกด RETURN สองครั้ง แล้วการกดครั้งที่สามจะสิ้นสุดและประมวลผล

การเติมข้อความอัตโนมัติ

ขณะพิมพ์คำสั่งใน REPL หากข้อความที่พิมพ์ไปแล้วตรงกับส่วนเริ่มต้นของชื่อบางอย่าง การกด TAB จะแสดงรายการที่เป็นไปได้ ตัวอย่างเช่น ก่อนอื่นนำเข้าโมดูล machine โดยพิมพ์ import machine แล้วกด RETURN จากนั้นพิมพ์ 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 แบบปกติ (หรือที่เรียกว่า friendly)

โหมด raw-paste เป็นโหมดเพิ่มเติมภายใน raw REPL ที่รวมการควบคุมการไหลของข้อมูล และคอมไพล์โค้ดขณะรับข้อมูล ทำให้มีความทนทานมากขึ้นสำหรับการถ่ายโอนโค้ดด้วยความเร็วสูงไปยังอุปกรณ์ และยังใช้ RAM น้อยลงขณะรับข้อมูลเพราะไม่จำเป็นต้องเก็บสำเนาโค้ดทั้งหมดก่อนคอมไพล์ (ต่างจากโหมด raw มาตรฐาน)

โหมด raw-paste ใช้โปรโตคอลดังต่อไปนี้:

  1. เข้าสู่ raw REPL ตามปกติผ่าน ctrl-A

  2. เขียน 3 ไบต์: b"\x05A\x01" (คือ ctrl-E แล้วตามด้วย "A" แล้วตามด้วย ctrl-A)

  3. อ่าน 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>"

  4. หากอุปกรณ์อยู่ในโหมด raw-paste ให้ดำเนินการต่อ มิฉะนั้นให้ใช้โหมด raw มาตรฐานแทน

  5. อ่าน 2 ไบต์ นี่คือค่าการเพิ่มขนาดหน้าต่างการควบคุมการไหล (เป็นไบต์) ที่เก็บเป็นจำนวนเต็มไม่มีเครื่องหมาย 16 บิต little endian ควรตั้งค่าเริ่มต้นของตัวแปร remaining-window-size เป็นตัวเลขนี้

  6. เขียนโค้ดไปยังอุปกรณ์:

    • ขณะที่ยังมีไบต์ที่ต้องส่ง ให้เขียนไบต์ได้มากสุดเท่ากับค่า remaining-window-size และลดค่า remaining-window-size ลงตามจำนวนไบต์ที่เขียน

    • หากค่า remaining-window-size เป็น 0 หรือมีไบต์รอการอ่าน ให้อ่าน 1 ไบต์ หากไบต์นี้คือ b"\x01" ให้เพิ่มค่า remaining-window-size ด้วยค่า window-size-increment จากขั้นตอนที่ 5 หากไบต์นี้คือ b"\x04" แสดงว่าอุปกรณ์ต้องการสิ้นสุดการรับข้อมูล และควรเขียน b"\x04" ไปยังอุปกรณ์และไม่ส่งโค้ดเพิ่มเติมหลังจากนั้น (หมายเหตุ: หากมีไบต์รอการอ่านจากอุปกรณ์ ไม่จำเป็นต้องอ่านและดำเนินการทันที อุปกรณ์จะดำเนินการรับไบต์ขาเข้าต่อไปตราบใดที่ค่า remaining-window-size มากกว่า 0)

  7. เมื่อเขียนโค้ดทั้งหมดไปยังอุปกรณ์แล้ว ให้เขียน b"\x04" เพื่อระบุสิ้นสุดข้อมูล

  8. อ่านจากอุปกรณ์จนกว่าจะได้รับ b"\x04" ณ จุดนี้อุปกรณ์ได้รับและคอมไพล์โค้ดทั้งหมดที่ส่งมาและกำลังรันอยู่

  9. อุปกรณ์จะแสดงผลตัวอักษรที่ผลิตโดยโค้ดที่กำลังรัน เมื่อ (ถ้า) โค้ดสิ้นสุด b"\x04" จะถูกส่งออก ตามด้วยข้อยกเว้นที่ไม่ถูกดักจับ แล้วตามด้วย b"\x04" อีกครั้ง จากนั้นจะกลับไปยัง raw REPL มาตรฐานและส่งออก b">"

ตัวอย่างเช่น เริ่มจากบรรทัดใหม่ใน REPL แบบปกติ (friendly) หากคุณเขียน:

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

ในกรณีนี้ค่า flow control window-size-increment คือ 128 และมีข้อมูลพร้อมใช้งานสองหน้าต่างทันทีตั้งแต่เริ่มต้น หนึ่งจากค่า window-size-increment เริ่มต้นและอีกหนึ่งจากค่า b"\x01" ที่ส่งมาอย่างชัดเจน ซึ่งหมายความว่าสามารถเขียนได้มากสุด 256 ไบต์ตั้งแต่เริ่มต้นก่อนที่จะรอหรือตรวจสอบอักขระการควบคุมการไหลขาเข้าเพิ่มเติม

เครื่องมือ MicroPython การควบคุมระยะไกล: mpremote ใช้ raw REPL รวมถึงโหมด raw-paste เพื่อรันโค้ด Python บน OpenMV Cams