DEV Community

codemee
codemee

Posted on

讓 MicroPython 輸入中文

MicroPython 不知道為了什麼原因,在實作的時候 input 內建函式只能接受 ASCII 字元,例如:

>>> r = input('請輸入:')
請輸入你好
WARNING: MicroPython ignores non-ascii characters of the input

>>> print(r)
Enter fullscreen mode Exit fullscreen mode

就會看到雖然好像輸入完成,但實際上印出輸入的文字時只會得到空字串。由於 input 不接受非 ASCII 字元,所以它 echo 回去的就是空字串, 在 Thonny 環境下會檢查 echo 回來的內容跟輸入內容是否相同,如果不相同,而且輸入內容含有非 ASCII 字元,就會顯示警告訊息,告知 MicroPython 的 input 不接受非 ASCII 字元。

好在如果直接使用 sys.stdin 取得的串流物件,就可以輸入中文了:

>>> import sys
>>> r = sys.stdin.readline()
你好
WARNING: MicroPython ignores non-ascii characters of the input
>>> print(r)
你好

>>>
Enter fullscreen mode Exit fullscreen mode

在互動窗格測試時,還是會看到警告訊息,這是因為我們沒有在收到輸入後 echo 回去,所以 Thonny 比對到的 echo 內容與輸入內容仍然不同,因此噴出警告訊息。只要將輸入內容原封不動 echo 回去,就不會看到警告訊息了:

>>> r = sys.stdin.readline();sys.stdout.write(r)
你好
7
>>> print(r.strip())
你好
>>> r = sys.stdin.readline();sys.stdout.write(r)
我是誰
10
>>> print(r.strip())
我是誰
>>>
Enter fullscreen mode Exit fullscreen mode

其中顯示的數字是 write 傳回的輸出字元數。因此,我們就可以利用這個方式撰寫客製版本的 input 函式了:

import sys
import select

def u_input(prompt):
    print(prompt, end='')    # 顯示提示
    r = sys.stdin.readline() # 讀取輸入
    sys.stdout.write(r)
    return r.strip()

while True:
    r = u_input('> ')
    print(r)
Enter fullscreen mode Exit fullscreen mode

實際測試都可以正常輸入中文:

>>> %Run -c $EDITOR_CONTENT

MPY: soft reboot
> 你好
你好
> 

> 我是誰
我是誰
> 

> 
Enter fullscreen mode Exit fullscreen mode

不過似乎都會多出換行字元,導致下一輪輸入時會直接被當成使用者已經按下了 Enter,底下加上接收輸入前先把輸入的暫存區清空的步驟:

import sys
import select

p = select.poll()     # 建立偵測物件
p.register(
    sys.stdin,        # 偵測標準輸入
    select.POLLIN     # 偵測是否有資料待讀取
) 

def u_input(prompt):
    if p.poll(0):            # 有資料待讀取
        sys.stdin.readline() # 先清空已輸入資料 
    print(prompt, end='')    # 顯示提示
    r = sys.stdin.readline() # 讀取輸入
    sys.stdout.write(r)
    return r.strip()

while True:
    r = u_input('> ')
    print(r)
Enter fullscreen mode Exit fullscreen mode

這樣就一切正常了:

>>> %Run -c $EDITOR_CONTENT

MPY: soft reboot
> 你好
你好
> 我是誰
我是誰
> 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)