Chế độ Trình thông dịch Tương tác MicroPython (hay còn gọi là REPL)¶
Phần này trình bày một số đặc điểm của Chế độ Trình thông dịch Tương tác MicroPython. Thuật ngữ phổ biến cho chế độ này là REPL (read-eval-print-loop -- đọc-đánh giá-in-lặp), và sẽ được dùng để chỉ dấu nhắc tương tác này.
Ghi chú
Các OpenMV Cam cung cấp REPL này qua cổng USB serial (CDC). Chế độ này chỉ có liên quan khi bạn kết nối trực tiếp với camera bằng trình giả lập terminal serial (hoặc công cụ như Điều khiển từ xa MicroPython: mpremote). OpenMV IDE không sử dụng REPL — nó giao tiếp với camera qua một giao thức gỡ lỗi riêng biệt để chạy tập lệnh, truyền tệp và truyền phát bộ đệm khung hình. Mọi nội dung mô tả trên trang này chỉ áp dụng cho các phiên terminal trực tiếp.
Tự động thụt lề¶
Khi gõ các câu lệnh Python kết thúc bằng dấu hai chấm (ví dụ: if, for, while), dấu nhắc sẽ chuyển thành ba chấm (...) và con trỏ sẽ được thụt vào 4 khoảng trắng. Khi bạn nhấn Enter, dòng tiếp theo sẽ tiếp tục ở cùng mức thụt lề cho các câu lệnh thông thường hoặc thêm một mức thụt lề khi phù hợp. Nếu bạn nhấn phím Backspace, một mức thụt lề sẽ được hoàn tác.
Nếu con trỏ đã ở đầu dòng, nhấn RETURN sẽ thực thi đoạn mã bạn đã nhập. Ví dụ dưới đây minh họa giao diện sau khi nhập một câu lệnh for (dấu gạch dưới chỉ vị trí con trỏ):
>>> for i in range(30):
... _
Nếu sau đó bạn nhập một câu lệnh if, hệ thống sẽ cung cấp thêm một mức thụt lề:
>>> for i in range(30):
... if i > 3:
... _
Bây giờ nhập break rồi nhấn RETURN và nhấn BACKSPACE:
>>> for i in range(30):
... if i > 3:
... break
... _
Cuối cùng gõ print(i), nhấn RETURN, nhấn BACKSPACE rồi nhấn RETURN thêm một lần:
>>> for i in range(30):
... if i > 3:
... break
... print(i)
...
0
1
2
3
>>>
Tính năng tự động thụt lề sẽ không được áp dụng nếu hai dòng trước đó toàn khoảng trắng. Điều này có nghĩa là bạn có thể kết thúc nhập một câu lệnh phức hợp bằng cách nhấn RETURN hai lần, và lần nhấn thứ ba sẽ hoàn tất và thực thi.
Tự động hoàn thành¶
Khi đang gõ lệnh tại REPL, nếu dòng đã gõ tương ứng với phần đầu tên của một đối tượng nào đó, nhấn TAB sẽ hiển thị các gợi ý có thể nhập tiếp. Ví dụ: trước tiên hãy import mô-đun machine bằng cách gõ import machine và nhấn RETURN. Sau đó gõ m và nhấn TAB -- nó sẽ mở rộng thành machine. Gõ dấu chấm . và nhấn TAB một lần nữa. Bạn sẽ thấy nội dung tương tự:
>>> machine.
__name__ info unique_id reset
bootloader freq rng idle
sleep deepsleep disable_irq enable_irq
Pin
Từ sẽ được mở rộng nhiều nhất có thể cho đến khi có nhiều khả năng. Ví dụ: gõ machine.Pin.PULL và nhấn TAB, nó sẽ mở rộng thành machine.Pin.PULL_. Nhấn TAB lần thứ hai sẽ hiển thị các khả năng mở rộng:
>>> machine.Pin.PULL_
PULL_DOWN PULL_UP
>>> machine.Pin.PULL_
Ngắt chương trình đang chạy¶
Bạn có thể ngắt chương trình đang chạy bằng cách nhấn Ctrl-C. Thao tác này sẽ phát sinh ngoại lệ KeyboardInterrupt, đưa bạn trở lại REPL, miễn là chương trình của bạn không bắt ngoại lệ KeyboardInterrupt.
Ví dụ:
>>> 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:
>>>
Chế độ dán¶
Nếu bạn muốn dán một đoạn mã vào cửa sổ terminal, tính năng tự động thụt lề sẽ làm rối mã. Ví dụ, nếu bạn có đoạn mã Python sau:
def foo():
print('This is a test to show paste mode')
print('Here is a second line')
foo()
và bạn cố dán đoạn mã đó vào REPL thông thường, bạn sẽ thấy nội dung như thế này:
>>> 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
Nếu nhấn Ctrl-E, bạn sẽ vào chế độ dán, về cơ bản tắt tính năng tự động thụt lề và thay đổi dấu nhắc từ >>> thành ===. Ví dụ:
>>>
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
>>>
Chế độ Dán cho phép dán các dòng trống. Văn bản được dán sẽ được biên dịch như thể là một tệp. Nhấn Ctrl-D để thoát chế độ dán và bắt đầu biên dịch.
Khởi động lại mềm¶
Lệnh Đặt lại mềm sẽ khởi động lại trình thông dịch Python nhưng cố gắng không đặt lại phương thức kết nối với OpenMV Cam (USB).
Bạn có thể thực hiện khởi động lại mềm từ REPL bằng cách nhấn Ctrl-D, hoặc từ mã Python của bạn bằng cách thực thi:
machine.soft_reset()
Ví dụ: nếu bạn khởi động lại OpenMV Cam và thực thi lệnh dir(), bạn sẽ thấy nội dung tương tự:
>>> dir()
['__name__']
Bây giờ tạo một số biến và lặp lại lệnh dir():
>>> i = 1
>>> j = 23
>>> x = 'abc'
>>> dir()
['j', 'x', '__name__', 'i']
>>>
Nếu nhấn Ctrl-D, rồi lặp lại lệnh dir(), bạn sẽ thấy các biến của mình không còn tồn tại:
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__']
>>>
Để biết thêm thông tin về các loại khởi động lại và quá trình khởi động, xem Trình Tự Khởi Động và Đặt Lại.
Biến đặc biệt _ (dấu gạch dưới)¶
Khi sử dụng REPL, bạn có thể thực hiện các phép tính và xem kết quả. MicroPython lưu kết quả của câu lệnh trước đó trong biến _ (dấu gạch dưới). Vì vậy, bạn có thể dùng dấu gạch dưới để lưu kết quả vào một biến. Ví dụ:
>>> 1 + 2 + 3 + 4 + 5
15
>>> x = _
>>> x
15
>>>
Chế độ thô và chế độ dán thô¶
Chế độ thô (còn gọi là raw REPL) không phải thứ người dùng thông thường sẽ dùng. Nó được thiết kế để sử dụng theo lập trình và về cơ bản hoạt động như chế độ dán nhưng tắt echo, kèm kiểm soát luồng tùy chọn.
Chế độ thô được vào bằng Ctrl-A. Sau đó bạn gửi mã Python, tiếp theo là Ctrl-D. Ctrl-D sẽ được xác nhận bằng 'OK', rồi mã Python sẽ được biên dịch và thực thi. Mọi đầu ra (hoặc lỗi) sẽ được gửi lại. Nhấn Ctrl-B sẽ thoát chế độ thô và trở lại REPL thông thường (hay còn gọi là friendly REPL).
Chế độ dán thô là một chế độ bổ sung trong raw REPL có kiểm soát luồng, và biên dịch mã khi nhận được. Điều này giúp nó ổn định hơn cho việc truyền mã tốc độ cao vào thiết bị, đồng thời sử dụng ít RAM hơn khi nhận vì không cần lưu bản sao nguyên văn của mã trước khi biên dịch (khác với chế độ thô tiêu chuẩn).
Chế độ dán thô sử dụng giao thức sau:
Vào raw REPL như thường lệ qua ctrl-A.
Ghi 3 byte:
b"\x05A\x01"(tức là ctrl-E rồi "A" rồi ctrl-A).Đọc 2 byte để xác định thiết bị có vào chế độ dán thô hay không:
Nếu kết quả là
b"R\x00"thì thiết bị hiểu lệnh nhưng không hỗ trợ dán thô.Nếu kết quả là
b"R\x01"thì thiết bị hỗ trợ dán thô và đã vào chế độ này.Ngược lại kết quả sẽ là
b"ra"và thiết bị không hỗ trợ dán thô, và chuỗib"w REPL; CTRL-B to exit\r\n>"nên được đọc và bỏ qua.
Nếu thiết bị ở chế độ dán thô thì tiếp tục, ngược lại chuyển sang chế độ thô tiêu chuẩn.
Đọc 2 byte, đây là mức tăng kích thước cửa sổ kiểm soát luồng (tính bằng byte) được lưu dưới dạng số nguyên không dấu 16-bit little endian. Giá trị khởi tạo cho biến remaining-window-size nên được đặt bằng số này.
Ghi mã ra thiết bị:
Trong khi còn byte để gửi, ghi tối đa remaining-window-size byte và giảm remaining-window-size đi số byte đã ghi.
Nếu remaining-window-size bằng 0, hoặc có byte đang chờ đọc, đọc 1 byte. Nếu byte này là
b"\x01"thì tăng remaining-window-size thêm window-size-increment từ bước 5. Nếu byte này làb"\x04"thì thiết bị muốn kết thúc nhận dữ liệu, vàb"\x04"nên được ghi vào thiết bị và không gửi thêm mã sau đó. (Lưu ý: nếu có byte đang chờ đọc từ thiết bị thì không cần đọc và xử lý ngay, thiết bị sẽ tiếp tục tiêu thụ byte đến miễn là remaining-window-size lớn hơn 0.)
Khi tất cả mã đã được ghi vào thiết bị, ghi
b"\x04"để báo hiệu kết thúc dữ liệu.Đọc từ thiết bị cho đến khi nhận được
b"\x04". Tại thời điểm này thiết bị đã nhận và biên dịch toàn bộ mã đã gửi và đang thực thi nó.Thiết bị xuất ra bất kỳ ký tự nào do mã thực thi tạo ra. Khi (nếu) mã hoàn thành,
b"\x04"sẽ được xuất ra, tiếp theo là mọi ngoại lệ chưa được bắt, rồi lạib"\x04". Sau đó thiết bị quay về raw REPL tiêu chuẩn và xuất rab">".
Ví dụ: bắt đầu từ một dòng mới tại REPL thông thường (friendly), nếu bạn ghi:
b"\x01\x05A\x01print(123)\x04"
Thì thiết bị sẽ phản hồi với nội dung tương tự:
b"\r\nraw REPL; CTRL-B to exit\r\n>R\x01\x80\x00\x01\x04123\r\n\x04\x04>"
Phân tích theo thời gian, điều này trông như thế này:
# 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>"
Trong trường hợp này, mức tăng kích thước cửa sổ kiểm soát luồng là 128 và có sẵn hai cửa sổ dữ liệu ngay từ đầu, một từ giá trị window-size-increment ban đầu và một từ giá trị b"\x01" tường minh được gửi. Vậy điều này có nghĩa là có thể ghi tới 256 byte ban đầu trước khi chờ hoặc kiểm tra thêm ký tự kiểm soát luồng đến.
Công cụ Điều khiển từ xa MicroPython: mpremote sử dụng raw REPL, bao gồm chế độ dán thô, để thực thi mã Python trên các OpenMV Cam.