UIFlowで大きめのMicroPythonスクリプトをimportする
概要
UIFlowはブロックを配置して簡単なプログラムを作るのに比較的便利なのですが、複雑な処理を記述するのには向いていません。
対策として、MicroPythonのスクリプトをimportして使いたくなるのですが、外部スクリプトをダウンロードしてimportする方法が用意されていません。
一方、UIFlowから使う画像などのリソースをダウンロードする機能があります。この機能は、画像ファイルしかダウンロード出来ないように見えますが、実は25[kB]以下であれば任意のファイルをダウンロードすることができます。
今回はこの機能を使ってMicroPythonスクリプトをダウンロードしてimportする方法と、25[kB]を越えるような大きなスクリプトの場合に取り得る対策について説明します。
MicroPythonスクリプトのダウンロード
スクリプトのダウンロードは、Resource Manager
から行います。
画面右上の MANAGER
とツールチップが表示されるボタンを押すと、Resource Manager
画面が表示されます。この画面は前述のとおり画像データをダウンロードするものですが、スクリプトもダウンロードできます。
Add Image
ボタンを押すとファイルを選択する画面が出てきます。Windowsの場合は以下のようなダイアログが表示され、フィルタとして *.bmp;*.dib;*.jfif;*.pjpeg;*.jpeg;*.pjp;*.jpg
が指定されているため、そのままではMicroPythonのスクリプト (*.py)が表示されません。
他のWindowsのアプリケーションと同様、フィルタをすべてのファイル
にすることにより、拡張子に関係なくファイルが表示されますので、MicroPythonのスクリプトも選択できるようになります。
注意点として、M5Stack/M5StickCのフラッシュROMで使っているファイルシステムの制約上、ファイル名は10文字以下の必要があります。
ここまでは、単にWindows上でのファイル操作入門みたいな話なので特に面白いことはありません。
以降、実験用に testmod.py
という名前で以下の内容のスクリプトをダウンロードしておきます。
hoge = 'hoge'
def hello() -> None:
print('hello ' + hoge)
ダウンロードしたスクリプトのimport
ダウンロードしたスクリプトは、ターゲットデバイス(M5Stack/M5StickC)のフラッシュROMに保存されます。
ただし、このままだとimport
文でインポートするときの検索パスではない場所に保存されているので、インポートに失敗します。
試しに、TeraTermなどのシリアルコンソールからREPLを操作してインポートしてみます。(UIFlowのファームウェアが動作しているので、Ctrl+C
を2~3回押してREPLの入力受付状態にします。)
M5Cloud connected.
m5cloud thread begin .....
mqtt reconnect
mqtt reconnect ok // <- この状態でCtrl+Cを3回入力
Unhandled exception in thread started by <bound_method>
Traceback (most recent call last):
File "flowlib/lib/time_ex.py", line 62, in timeCb
KeyboardInterrupt:
Unhandled exception in thread started by <bound_method>
Traceback (most recent call last):
File "flowlib/m5cloud.py", line 178, in _daemonTask
File "flowlib/lib/time_ex.py", line 62, in timeCb
KeyboardInterrupt:
Traceback (most recent call last):
File "flow.py", line 42, in <module>
File "flowlib/m5cloud.py", line 215, in run
File "flowlib/m5cloud.py", line 190, in _backend
File "flowlib/m5cloud.py", line 178, in _daemonTask
File "flowlib/lib/time_ex.py", line 62, in timeCb
KeyboardInterrupt:
MicroPython v1.11-294-gf32fecff7-dirty on 2019-08-30; ESP32 module with ESP32
Type "help()" for more information.
>>>
>>> import testmod
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: no module named 'testmod'
>>>
testmod
というモジュールは無いと言われてしまいました。
MicroPythonでは、モジュールはsys.path
のリストに含まれるパスから検索されます。UIFlowのファームウェアでは、以下のとおり ['', '/lib', 'flowlib', 'flowlib/lib']
となっています。
>>> import sys
>>> sys.path
['', '/lib', 'flowlib', 'flowlib/lib']
>>>
一方、ダウンロードしたスクリプトは、/flash/res
に保存されています。
>>> import os
>>> os.listdir('/flash/res')
['default.jpg', 'error.jpg', 'wisun.mpy', 'testmod.py']
>>>
よって、/flash/res
を sys.path
に追加すると、UIFlowのResource Managerでダウンロードしたスクリプトをインポートできるようになります。
>>> sys.path.append('/flash/res')
>>> import testmod
>>> testmod.hello()
hello hoge
>>> testmod.hoge
'hoge'
>>>
UIFlowで同じことを行うには、以下のようにブロックをつなぎます。
大きいスクリプトのダウンロード
前述の通り、UIFlowのResource Managerでダウンロードできるファイルサイズは25[kB]に制限されています。
また、この制限を越えない場合でも、あまり大きいスクリプトをインポートしようとすると、memory allocation errorが発生する場合があります。
memory allocation errorが発生するのは、インポート時にターゲットデバイス上でスクリプトをバイトコードにコンパイルするときに、スクリプトが大きすぎるためメモリ不足になるためです。
これらの対策としては、PC上で事前にバイトコードにコンパイルしておくという方法があります。
バイトコードコンパイルを行うために、公式のMicroPythonには mpy-cross
というツールが用意されています。MicroPythonをビルドすると、mpy-cross/mpy-cross
以下に実行可能ファイルが生成されます。
このツールにMicroPythonスクリプト (.py)を指定して実行すると、同じディレクトリに元のスクリプトと同じファイル名で拡張子が `.mpy` のファイルが出力されます。この .mpy ファイルを Resource Manager経由でダウンロードすれば、.pyと同様にインポートできるようになります。
今のところ、M5StickC用のWi-SUN HAT制御用のモジュールが25[kB]を越えており700行超あるため、Resource Managerの制約に引っかかる上、ほかの方法でダウンロードしてインポートしてもmemory allocation errorで失敗します。
このスクリプトをmpyに変換したところ、Resource Managerでダウンロードしして正常にimportできるようになっています。
興味のある方は、前に書いた MicroPythonのビルド記事 を見ていただければ、お試しいただけると思います。
現時点では MicroPython をビルドしたうえで mpy-cross
を使うという手順が必要なためハードルが高いと思われますので、何かしらツールを用意しようかなと考えています。
アップロードしたスクリプトをコンパイルしてダウンロードするサイトを用意しましたのでお試しください。 https://micropythonbytecodeconverter.azurewebsites.net/
Author And Source
この問題について(UIFlowで大きめのMicroPythonスクリプトをimportする), 我々は、より多くの情報をここで見つけました https://qiita.com/ciniml/items/68bc7f362d6985efc640著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .