关于MicroPython mpremote工具 的一些用例,闲聊


我尝试了很多不同的第三方micropython工具,有些是Windows应用程序,有些是VScode插件。

但是当我尝试过MicroPython的mpremote工具后,我几乎决定它将成为我的首选工具。??

我通常将其与VScode结合使用。它的代码突出显示,自动完成和自动缩进非常有用。同时打开其他插件也很容易。另外VScode也是一个多平台的IDE,我比较习惯在几个不同的操作系统里用同一个IDE,来回切换不会生手。

也许有些极简主义者,我认为mpremote工具也会很合适,只需将系统的终端与任何文本编辑器一起使用即可,如果你是命令行老手,则只需要一个终端即可完成所有操作。

目录 (Table of Contents)

目录
  • PyPI 页面 在终端用pip install mpremote命令即可安装。(推荐)

    GitHub 页面

    MicroPython文档页面

    本文在GitHub micropython/discussions/9096的页面

    1. cp

    这可能是除 repl 之外最常见的命令,用于将文件从本地复制到设备,或从设备复制到本地。可能是因为我还不熟悉终端命令语法,起初我无法从MicroPython文档中的几个用例中完全掌握cp命令的用法,反复运用和尝试后就渐渐上手了。

    1.1 在终端的当前路径中复制文件

    首先创建一个干净的临时文件夹,并在其中写入一个main.py文件。

    print ("start")
    for i in range(2):
        print(i)
    print ("end")
    

    最简单的用例,在终端中输入此文件夹路径,将文件从本地复制到设备:

    mpremote connect COM1 cp main.py : 
    
    mpremote connect COM1 cp main.py :main.py
    

    这两个命令实现完全相同的功能。

    :符号之后,如果输入文件名,则文件在复制到设备时将重命名为此文件名。

    将文件从设备复制到本地 :

    mpremote connect COM1 cp :main.py .
    
    mpremote connect COM1 cp :main.py main.py
    

    这两个命令实现完全相同的功能。

    如果要重命名,可以删除.符号并输入所需的文件名。

    1.2 复制绝对路径中的文件

    它有点复杂。

    在 Windows 上,使用文件的绝对路径从本地复制到设备:

    mpremote connect COM1 cp D:\temp\main.py :main.py
    

    将文件从设备复制到本地 :

    mpremote connect COM1 cp :main.py D:\temp\main.py
    

    目前在mpremote 0.3.0版本,应特别注意在Windows中不能省略目标文件名!
    我在 GitHub 上已提交PR #9148 对 Windows 路径名分隔符的支持,下一个版本应该就可以随意在Windows里使用相对路径和绝对路径了,不影响其他功能。

    在 Linux(如 Ubuntu)中,从绝对路径复制文件可以省略目标文件名:

    mpremote connect /dev/ttyACM0 cp ~/temp/main.py :
    
    mpremote connect /dev/ttyACM0 cp /home/wind/temp/main.py :
    
    mpremote connect /dev/ttyACM0 cp :main.py ~/temp/
    
    mpremote connect /dev/ttyACM0 cp :main.py /home/wind/temp/
    

    1.3 同时复制多个文件

    在Linux中,例如Ubuntu,将多个文件从本地复制到具有绝对路径的设备:

    mpremote connect /dev/ttyACM0 cp ~/temp/main.py ~/temp/main2.py :
    

    将多个文件从设备复制到本地绝对路径:

    mpremote connect /dev/ttyACM0 cp :main.py :main2.py ~/temp/
    

    2. exec, run

    这些命令用于控制远程设备在不复制文件的情况下运行 Python 代码或脚本。

    2.1 执行给定的 Python 代码

    mpremote connect COM1 exec "print(1234)"
    

    就像在REPL中输入一行Python代码一样。

    2.2 从本地文件系统运行脚本

    mpremote connect COM1 run test_1.py
    

    就像在REPL中进入粘贴模式一样,将代码复制并粘贴到指定的Python脚本中,然后运行它。

    3. mount

    我未曾想过有这种使用MicroPython设备的方法,请看以下用例并尝试理解它,随后你就会像我一样对这个功能爱不释手~~

    3.1 在远程设备上挂载本地目录

    首先创建一个干净的临时目录,并在其中写入一些Python脚本,如下所示:

    # numbers.py
    num_1 = 21
    num_2 = 22
    num_3 = 23
    num_4 = 24
    
    
    # test_1.py
    print("test_1 start")
    import numbers
    print(numbers.num_1)
    print(numbers.num_2)
    print(numbers.num_4)
    print("test_1 end")
    
    
    # test_2.py
    print("test_2 start")
    import numbers
    temp1 = numbers.num_3 - numbers.num_2
    print(temp1)
    temp1 = numbers.num_3 - numbers.num_1
    print(temp1)
    print("test_2 end")
    
    

    在终端中输入此目录的路径。

    我们先确认一些信息,列出设备上的文件:

    mpremote connect COM1 ls
    
    ls :
             139 boot.py
    

    进入 REPL 并再次确认:

    mpremote connect COM1 repl
    
    >>> uos.listdir()
    ['boot.py']
    >>>
    

    退出 REPL,挂载本地目录,再次进入 repl:

    mpremote connect COM1 mount . repl
    

    再次确认文件:

    >>> uos.listdir()
    ['numbers.py','test_1.py', 'test_2.py']
    

    这里没有boot.py,但我们在本地目录创建的Python脚本出现在列表中。

    导入并运行两个测试脚本:

    >>> import test_1,test_2
    test_1 start
    21
    22
    24
    test_1 end
    test_2 start
    1
    2
    test_2 end
    >>>
    

    查看一个文件:

    >>> f=open("numbers.py")
    >>> print(f.read())
    # numbers.py
    num_1 = 21
    num_2 = 22
    num_3 = 23
    num_4 = 24
    
    >>>
    

    惊讶之余,你可能想知道,这些python脚本文件是不是全部都上传到设备上并存储起来了?我最初也是这么猜测的。

    现在,我们将终端保留在REPL中,在本地修改此文件:

    # numbers.py
    num_1 = 1
    num_2 = 12
    num_3 = 23
    num_4 = 35
    
    

    返回 REPL 并再次检查:

    >>> f=open("numbers.py")
    >>> print(f.read())
    # numbers.py
    num_1 = 1
    num_2 = 12
    num_3 = 23
    num_4 = 35
    
    >>>
    

    这样就解除疑惑了,文件只保存在本地目录中,并且这个目录被挂载在设备上。

    软件重置后,并将重新挂载目录。

    这就像是一个移动硬盘,或者是说像是NAS,云盘,连在MicroPython设备上,显然这个功能能极大节约设备的flash寿命,通常只需要在必须脱机运行的时候再把python脚本文件拷贝到flash里即可。

    推荐使用以下组合命令执行python脚本:

    mpremote connect COM1 mount . exec "import test_1"
    

    3.2 在挂载了本地目录后继续使用原flash中的脚本

    在REPL中使用uos.listdir("/")命令你将看到原来存储在flash中的文件:

    >>> uos.listdir("/")
    ['remote', 'boot.py', 'main.py']
    

    如果你想保持挂载本地目录的状态下使用flash中的脚本(例如main.py),你可以使用如下命令将原flash根目录路径添加进sys.path列表中:

    >>> import sys
    >>> sys.path
    ['', '.frozen', '/lib']
    >>> sys.path.append("/")
    >>> sys.path
    ['', '.frozen', '/lib', '/']
    >>> import main
    

    如果挂载的本地目录中已有main.py,则仅会运行本地目录的main.py,可通过reverse()调换列表顺序:

    >>> sys.path
    ['', '.frozen', '/lib', '/']
    >>> sys.path.reverse()
    >>> sys.path
    ['/', '/lib', '.frozen', '']
    >>> import main
    

    现在就会优先运行flash中的脚本。

    3.3 加快测试速度的一种方法

    如果我们需要对一个脚本一遍测试一遍修改,而脚本中已经导入了很多存储在本地的脚本模块,这样的情况下,每一次挂载测试都将花费数秒甚至数十秒的时间。

    我总结了一种方法,在REPL中设法不重复的import模块即可有效减少运行时间。

    以测试SSD1306 OLED显示屏为例,main.py是主程序,ssd1306.py是驱动模块,此处就不再完整列举程序代码了。

    通过time.tick_ms()来验证测试本地目录的main.py脚本所需的时间,可见大概需要6秒:

    >>> import time;t1 = time.ticks_ms();import main;time.ticks_diff(time.ticks_ms(),t1)
    6032
    

    使用sys.modules可以查看当前已经导入的脚本模块,可见ssd1306.py已经导入:

    >>> import sys;sys.modules
    {'main': , 'ssd1306': , 'flashbdev': }
    

    我们仅需移除main而保留其他的模块:

    >>> del main;sys.modules.pop('main')
    
    >>> import sys;sys.modules
    {'ssd1306': , 'flashbdev': }
    

    再次测试:

    >>> import time;t1 = time.ticks_ms();import main;time.ticks_diff(time.ticks_ms(),t1)
    1612
    

    得到明显改善。