micropython --- 存取與控制 MicroPython 內部機制¶
函式¶
- micropython.const(expr: int) int¶
用於宣告該運算式為常數,使編譯器得以最佳化它。此函式的使用方式應如下所示:
from micropython import const CONST_X = const(123) CONST_Y = const(2 * CONST_X + 1)
以此方式宣告的常數仍可作為全域變數,從宣告它的模組外部存取。另一方面,若常數以底線開頭,則它會被隱藏,無法作為全域變數使用,並且在執行期間不會佔用任何記憶體。
此
const函式會被 MicroPython 剖析器直接辨識,並作為micropython模組的一部分提供,主要是為了讓所撰寫的指令碼可以依循上述模式同時在 CPython 與 MicroPython 下執行。
- micropython.opt_level(level: int | None = None) int | None¶
若有給定 level,則此函式會設定後續指令碼編譯的最佳化等級,並回傳
None。否則它會回傳目前的最佳化等級。最佳化等級控制下列編譯特性:
斷言:在等級 0 時,斷言陳述式會被啟用並編譯進位元組碼;在等級 1 及以上時,斷言不會被編譯。
內建
__debug__變數:在等級 0 時,此變數會展開為True;在等級 1 及以上時,它會展開為False。原始碼行號:在等級 0、1 與 2 時,原始碼行號會與位元組碼一同儲存,以便例外能回報其發生的行號;在等級 3 及以上時,行號不會被儲存。
預設的最佳化等級通常為等級 0。
- micropython.alloc_emergency_exception_buf(size: int) None¶
為緊急例外緩衝區配置 size 位元組的 RAM(理想大小約為 100 位元組)。此緩衝區用於在正常 RAM 配置會失敗的情況下(例如在中斷處理常式內)建立例外,從而在這些情況下提供有用的回溯資訊。
使用此函式的一個好方法是將它放在主指令碼的開頭(例如
boot.py或main.py),如此一來,緊急例外緩衝區便會對其後所有的程式碼生效。
- micropython.mem_info(verbose: Any | None = None) None¶
印出目前使用的記憶體資訊。若有給定 verbose 引數,則會印出額外資訊。
所印出的資訊取決於實作,但目前包含已使用的堆疊與堆積數量。在 verbose 模式下,它會印出整個堆積,標示出哪些區塊已使用、哪些為空閒。
- micropython.qstr_info(verbose: Any | None = None) None¶
印出目前已駐留(interned)字串的資訊。若有給定 verbose 引數,則會印出額外資訊。
所印出的資訊取決於實作,但目前包含已駐留字串的數量以及它們所使用的 RAM 量。在 verbose 模式下,它會印出所有 RAM 駐留字串的名稱。
- micropython.heap_lock() None¶
鎖定堆積。在鎖定期間,不會發生任何記憶體配置,且若嘗試任何堆積配置都會引發
MemoryError。鎖定可巢狀:多次呼叫
heap_lock()會增加鎖定深度。堆積會維持鎖定狀態,直到heap_unlock()被呼叫相同次數為止。若 REPL 在堆積鎖定的情況下變為作用中,則它會被強制解鎖。
- micropython.kbd_intr(chr: int) None¶
設定將引發
KeyboardInterrupt例外的字元。在指令碼執行期間,預設此值設為 3,對應於 Ctrl-C。將 -1 傳入此函式會停用 Ctrl-C 的擷取,傳入 3 則會還原它。此函式可用於防止在通常用於 REPL 的傳入字元串流上擷取 Ctrl-C,以因應該串流被用於其他用途的情況。
- micropython.schedule(func: Callable[[Any], Any], arg: Any) None¶
排程函式 func 「很快」被執行。該函式會以 arg 值作為其唯一引數傳入。「很快」意指 MicroPython 執行期會盡力在最早可能的時間執行該函式,前提是它同時也試圖保持高效,且下列條件成立:
已排程的函式絕不會搶佔另一個已排程的函式。
已排程的函式總是在「運算碼之間」執行,這意味著所有基本的 Python 操作(例如附加至串列)都保證是不可分割的(atomic)。
特定的移植版本可能會定義「臨界區(critical region)」,在其中已排程的函式絕不會被執行。函式可以在臨界區內被排程,但要等到該區結束後才會執行。臨界區的一個例子是搶佔式中斷處理常式(IRQ)。
在原生程式碼函式內,已排程的函式不會被呼叫,除非該原生程式碼呼叫了某個會特別這麼做的函式。
某些函式,包括
poll.poll、poll.ipoll、time.sleep與time.sleep_ms(包含零時長的睡眠),會呼叫已排程的函式。
此函式的一個用途是從搶佔式 IRQ 排程回呼。這類 IRQ 對在其中執行的程式碼施加限制(例如堆積可能被鎖定),而排程一個稍後呼叫的函式便可解除這些限制。
在多執行緒移植版本上,已排程函式的行為取決於該特定移植版本是否啟用全域直譯器鎖(GIL):
若啟用 GIL,該函式可以搶佔任何執行緒並在其情境中執行。
若停用 GIL,該函式只會搶佔主執行緒並在其情境中執行。
註:若
schedule()是從搶佔式 IRQ 呼叫(此時不允許記憶體配置),且要傳給schedule()的回呼是繫結方法(bound method),直接傳入它會失敗。這是因為建立對繫結方法的參考會導致記憶體配置。解決方法是在類別建構函式中建立對該方法的參考,並將該參考傳給schedule()。此問題在「Creation of Python objects」一節的 參考文件 中有詳細討論。用於存放已排程函式的佇列是有限的,若佇列已滿,
schedule()會引發RuntimeError。
類別¶
- class micropython.RingIO(size: int)¶
- class micropython.RingIO(buffer: bytes | bytearray | memoryview)
為位元組提供具有串流介面的固定大小環形緩衝區(ringbuffer)。可視為
io.BytesIO的 FIFO 佇列變體。兩種建構函式形式的差異僅在於後備緩衝區的提供方式:RingIO(size)會在內部配置後備緩衝區。經典的環形緩衝區演算法會保留一個位元組用於追蹤,因此所配置的緩衝區會比size大一個位元組,而該實例可容納完整size位元組的資料。例如,RingIO(16)會配置一個 17 位元組的緩衝區,並容納 16 位元組的資料。RingIO(buffer)會就地使用所提供的buffer,而非自行配置。由於有一個位元組保留用於追蹤,該實例可容納len(buffer) - 1位元組的資料。例如,RingIO(bytearray(16))容納 15 位元組的資料。
當 RingIO 實例用於單一方向傳遞資料時(例如從 IRQ 寫入、由非 IRQ 函式讀取,或反之),它是 IRQ/執行緒安全的。但若單一實例同時從 IRQ 與非 IRQ 情境寫入,此保證便不成立,這通常會導致資料損毀。
- read(nbytes: int | None = None) bytes¶
讀取可用的字元。這是一個非阻塞函式。若有指定
nbytes,則最多讀取該數量的位元組,否則盡可能讀取最多的資料。回傳值:一個包含所讀取位元組的 bytes 物件。若無可用資料,則為長度為零的 bytes 物件。
- readline(nbytes: int | None = None) bytes¶
讀取一行,以換行字元結尾,若緩衝區中存在則回傳,否則回傳緩衝區中的可用位元組。若有指定
nbytes,則最多讀取該數量的位元組。回傳值:一個包含所讀取行的 bytes 物件。
- readinto(buf: bytearray | memoryview, nbytes: int | None = None) int¶
將可用的位元組讀取至所提供的
buf中。若有指定nbytes,則最多讀取該數量的位元組。否則最多讀取len(buf)位元組。回傳值:讀取至
buf的位元組數量的整數計數。
- write(buf: bytes | bytearray | memoryview) int¶
從
buf將位元組非阻塞地寫入環形緩衝區,受限於環形緩衝區中的可用空間。回傳值:所寫入位元組數量的整數計數。