micropython on ESP32 でモジュールをインストールする
micropythonにはPyPiサイトに用意されたモジュールをインストールするためのモジュール upip が用意されています。
import upip upip.install("パッケージ名")
でインストールできます。
ちなみに、upipのソースはmicropython-esp32/esp32/modules/upip.pyにあり、micropython本体に組み込まれています。
しかし、サーバアドレスが固定されているため、自分で作ったモジュールをインストールするには使用できません。
また、PyPiサイトのモジュール管理形式を使用しているため、URLを自分のサーバに変えるだけではうまくいきません。
そこで、upipもどきなモジュール upipm (例によって「もどき」の「m」を追加)を作ってみました。
BaseURL で指定されたURLからget_file()の第1パラメータで指定したファイルを第2パラメータで指定したディレクトリに保存します。
ダウンロード元はHTTPサーバでなければなりません(Espruinoで作ったmnpmと同じです)。
import sys import gc import uos as os gc.collect() debug = False # Base URL BaseURL = "http://192.168.78.80/py_modules/"# 自分の環境に合わせて修正してくさだい class NotFoundError(Exception): pass import ussl import usocket warn_ussl = True def url_open(url): global warn_ussl if debug: print(url) proto, _, host, urlpath = url.split('/', 3) if debug: print("proto:%s, host:%s, urlpath:%s" % (proto, host, urlpath)) if proto == "https:": port = 443 else: port = 80 try: ai = usocket.getaddrinfo(host, port) except OSError as e: fatal("Unable to resolve %s (no Internet?)" % host, e) if debug: print("Address infos:", ai) addr = ai[0][4] s = usocket.socket(ai[0][0]) try: if debug: print("Connect address:", addr) s.connect(addr) if proto == "https:": s = ussl.wrap_socket(s) if warn_ussl: print("Warning: %s SSL certificate is not validated" % host) warn_ussl = False # MicroPython rawsocket module supports file interface directly s.write("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (urlpath, host)) l = s.readline() if debug: print(l) protover, status, msg = l.split(None, 2) if status != b"200": if status == b"404" or status == b"301": raise NotFoundError("File not found") raise ValueError(status) while 1: l = s.readline() if debug: print(l) if not l: raise ValueError("Unexpected EOF in HTTP headers") if l == b'\r\n': break except Exception as e: s.close() raise e return s def fatal(msg, exc=None): print("Error:", msg) if exc and debug: raise exc sys.exit(1) def get_file(name, distdir=None): if distdir is None: distdir = sys.path[1] if distdir[-1] != "/": distdir += "/" f = url_open(BaseURL + name) print("==== START ====") with open(distdir + name, "wb") as outf: while True: l = f.readline() if not l: break outf.write(l, len(l)) # print(len(l)) print(l) print("==== DONE ====") def help(): print("""\ upipm - Simple PyPI package manager **MODOKI** for MicroPython Usage: import upipm; upipm.get_file(name, [<path>]) If <path> is not given, packages will be installed into sys.path[1]. """) print("Current value of sys.path[1]:", sys.path[1]) if __name__ == "__main__": def main(): get_file("upipm.py") if __name__ == "__main__": main()
BaseURLは自分の環境に合わせて変更しておいてください。
また、オンボードストレージに/libディレクトリが存在しない場合は、以下のように実行してディレクトリを作成しておいてください。
import uos uos.chdir("/") uos.listdir() ==> ['boot.py'] uos.mkdir("/lib") uos.listdir() ==> ['boot.py', 'lib']
このプログラムのファイルをupipm.pyという名前でBaseURLの場所に格納しておき、プログラム自体をコンソールからコピペして実行すると、upipm.pyがインストールされます。
以下のように実行すると正常にインストールできたか確認できます。
import uos uos.listdir("/lib") ==> ['upipm.py']
インストール後は、以下のように実行すると任意のファイルをインストールできます。
モジュール単位でのインストールではなく、ファイル単位なので、ファイル拡張子(.py)も忘れずに指定してください。
デフォルトのインストール先はsys.path[1](ESP32の場合は/lib)です。
import upipm upipm.get_file("ファイル名")
また、第2パラメータにはインストール先を指定することも可能です。
たとえば、こんな感じ。
upipm.get_file("boot.py", "/")