モダンOSのお砂場(10) MicroPython、モジュールとhelp

JosephHalfmoon
JosephHalfmoon

皆さまは、PythonのREPL(Read-Eval-Print Loop)使っておられますか?実を申せば、私はPC上のPythonではまず使いません。ほとんどバッチでPythonスクリプトを走らせているから。インタラクティブなデバッグしたいときはpdb起動しているし… でも今回K210をCPUに頂くM5StickV上のMicroPythonを使うにあたってREPL使うことにいたしました。help()関数、使わねばね。

まだ慣れないせいでしょうが、ターミナルエミュレータからM5StickVのMicroPythonのREPLループに入り込んでスクリプトを書いているとき、どのドキュメントをみるべきかちょっと迷います。それは、Kendryte K210(CPUコアはRISC-V)チップを内蔵するM5StickVのMicroPythonの「重層性」に慣れない、ということでもあります。

  1. ご本家、Pythonの公式ドキュメント(Python 3.8.1)
  2. MicroPython.org
  3. MaixPyのドキュメント
  4. M5Stack.com内のM5StickV関係情報(リンクはMaixPy Exampleページ)

Python書いているときは、1.のPython.org内のドキュメントを読めば事足ります。リンク張ったのはPython 3.8.1です。私の場合、一部で 3.7系の処理系も併用しているので本当に細かいところだけバージョンの選択気を付けますが(蛇足ながら本年元旦からはスッパリ2.7系の使用を止めました)、公式には日本語のドキュメントもあり、楽ちんな環境です。

当然、MicroPythonは、Pythonとは異なる部分があるので、MicroPythonそのものについては、2.のMicroPython.orgを参照させてもらっています。ここも日本語ページあります。当然ながら、

MicroPython Differences

という「一般的な」Python(CPython)との違いを記したページが存在し、違いを解説しています。MicroPython自体は、Damien Georgeという人が始められたプロジェクトである、とあります。MicroPython.orgの著作権表示は George Robotics Limited という法人になっています。見れば、この法人は、物販もやっていて、

pyboard

というMicroPythonを搭載した小型マイコンボードが主力製品であるようです。そのため、MicroPythonのホームページで「スタンダード」的な実装として扱われているのはこのpyboard系のものです。使用されているマイコンはSTマイクロエレクトロニクスのSTM32系のマイコン、コアはArmですね。当然、ここみてもK210上の実装の情報は出てきません。

そこで参照させてもらうのが、Kindryte K210にMicroPythonを移植したSipeed社の 3. のドキュメントです。この会社は、AI + IoT で AIoTだ、というようなスローガンで、エッジ系のAI応用の各種モジュール、ボード製品など売っている会社に見えます。そのなかで、MicroPythonをK210上に移植した環境である MaixPyはそれらの自社製品を利用する上で重要なソフトウエア基盤となっているように見えます。K210チップ特有の実装はここを見ないとなりません。

そして最後が、M5Stackのホームページの中のM5StickV関係の情報ページです。M5Stack自体は、M5Stack、M5Stickの名を持つオールインワン的な小型マイコン装置を販売していて、その中の一機種がM5StickVという位置づけでよいかと思います。主力はEsprissif社のESP32系のSoCプロセッサを使用した製品です。MicroPythonもESP32系へのポートが中心で、今のところRISC-VコアのK210を搭載したM5StickVは、ちょっと毛色の違った機種としてリストされている感じ。当然、M5StickVのLCDやセンサやスイッチなどの現物ハードウエア構成に即した例題プログラムなどがここには存在します。しかし、ボーっと生きているとESP32系のMicroPythonの実装(MicroPythonとしての根本は同じ筈だが、モジュールは異なる)を見ることになってしまうので気をつけないと。

そんな重層構造なので、M5StickVの実機にインストールしてある実ソフトウエアの構成は実物に聞いておく、のが「一番確か」かもしれません。PC上のPythonとの挙動の違いもいろいろあったので、書き留めておきます。

まず、何も引数を与えず REPL上で help() と打つとどうなるかです。PC上のPython3では、helpプロンプトが出て、調べるべきキーワードの入力待ちとなります。

>>> help()

Welcome to Python 3.8's help utility!
~以下略~
help>

しかし、MicroPythonでは、参照先のURL、コントロールキーの使いかたとモジュールをリストする方法などを列挙する定型のドキュメントが表示されるだけです。なお、コントロールキーの使い方で

  • Raw REPL
  • paste mode

といったものが出てきますが、このあたりは、MicroPythonの文書(日本語ページ)の対話インタプリタモードにちゃんと説明されているので、そちらを読めばよく分かると思います。

さて、CPythonもMicroPythonも、インストールされているモジュール名を列挙するならば、

>>> help('modules')

でリストされるところは同じです。しかし、helpに渡す引数によっては挙動が異なりました。CPythonであれば、まだ import していないモジュールであっても

>>> help('sys')

などとすれば、そのモジュールのhelpが表示されます。また、モジュール以外の言語要素、例えば if なども、

>>> help('if')

で説明を読むことができます。しかし、MicroPythonで help(‘sys’)などとすると

object sys is of type str
~以下略~

str型のオブジェクトが持つ関数が列挙されてしまいます。’sys’や’if’などは単なる文字列として解釈され、str型のhelpを表示するみたいです。どうも

‘modules’

だけは特例のようです。よって、MicroPythonでモジュールのhelpを読みたかったら、「正式に」importしてオブジェクトにしてから実行するべきです。(こちらの方法はCPythonでも勿論OK)

>>> import KPU
>>> help(KPU)
object <module 'kpu'> is of type module
  __name__ -- kpu
  load -- <function>
~以下略~

などとすれば、K210の最大の売りである AI用アクセラレータKPU用のモジュールが持つ関数リストを引き出すことができます。

しかし、関数や変数などのモジュール内のオブジェクトを列挙するのであれば、help()関数よりも、dir()関数を使った方が実効的かもしれません。例えば、K210の入出力ピンの制御を引き受けてくれる fpioa_managerというモジュールが存在するのですが、help()だと以下のような情報しか出てきません。

>>> help(fpioa_manager)
object <module 'fpioa_manager'> is of type module
  board_info -- <Board_Info object at 80217720>
  fm -- <Fpioa_Manager object at 80217e60>
  Fpioa_Manager -- <class 'Fpioa_Manager'>
  FPIOA -- <class 'FPIOA'>
  __name__ -- fpioa_manager
>>> help(fpioa_manager.board_info)
object <Board_Info object at 80217720> is of type Board_Info
  __module__ -- board
  __init__ -- <function __init__ at 0x80217900>
  pin_map -- <function pin_map at 0x80217960>
  __qualname__ -- Board_Info

しかし、dir()関数で、fpioa_manager.board_infoをリストしてみると、

>>> dir(fpioa_manager.board_info)
['__class__', '__init__', '__module__', '__qualname__', '__dict__', 'pin_map', 'pin_num', 'ISP_RX', 'ISP_TX', 'WIFI_TX', 'WIFI_RX', 'CONNEXT_A', 'CONNEXT_B', 'MPU_SDA', 'MPU_SCL', 'MPU_INT', 'SPK_LRCLK', 'SPK_BCLK', 'SPK_DIN', 'SPK_SD', 'MIC_LRCLK', 'MIC_DAT', 'MIC_CLK', 'LED_W', 'LED_R', 'LED_G', 'LED_B', 'BUTTON_A', 'BUTTON_B', 'pin_name']

>>> print(fpioa_manager.board_info.BUTTON_A)
36
>>> print(fpioa_manager.board_info.BUTTON_B)
37
>>> print(fpioa_manager.board_info.LED_W)
7
>>> print(fpioa_manager.board_info.LED_R)
6

オブジェクト内でプリディファインされているピン番号の名前などを全て引き出すことができます。help()で引き出せる情報多くないから、こちらの方が実用的かな~。

定数名など忘れたら

dir(オブジェクト名)

モダンOSのお砂場(10) MicroPython、ファイルにアクセス へ戻る

モダンOSのお砂場(12) MicroPython、GPIO入出力 へ進む