春满情缘 發表於 2026-4-4 17:07:00

ESP32 实现在线动态安装库和自动依赖安装-使用uPyPI包管理平台

<h1 id="引言">引言</h1>
<p>做 MicroPython 嵌入式开发的你,是不是每天都在被这些问题折磨?<br>
写好的代码一运行就报错,翻遍半天发现​<strong>少装了一个依赖文件</strong>​;更崩溃的是,一个库要带好几个附属文件,漏一个就全盘报废。<br>
这里,我们需要先引出<strong>依赖库</strong>的概念,在 MicroPython 开发中,<strong>依赖库</strong>的官方定义非常清晰:</p>
<blockquote>
<p>你的主功能代码 / 主库,无法独立正常运行,必须调用其他独立的 <code>.py</code> 代码文件提供的​<strong>函数、类、硬件接口、算法逻辑</strong>​,这些被调用的外部代码文件,就是​<strong>依赖库</strong>​。</p>
</blockquote>
<p>举一个嵌入式真实案例:用 ESP32 驱动 MAX30102 传感器,做<strong>心率血氧检测</strong></p>
<ul>
<li>主功能文件:<code>heart_rate.py</code>(负责:心率计算、数据显示、异常报警)</li>
<li>依赖库文件 1:<code>max30102.py</code>(负责:传感器底层硬件读写、寄存器配置)</li>
<li>依赖库文件 2:<code>filter_lib.py</code>(负责:波形滤波、噪声消除算法)</li>
</ul>
<p><code>心率主程序</code> → 必须调用 <code>传感器驱动</code> + <code>滤波算法</code> 才能运行没有这两个依赖库,你的心率代码直接报错,完全跑不起来。</p>
<p>再延伸一个真实开发场景:</p>
<ul>
<li>你安装的某个 <code>WiFi联网某某功能库</code>,可能依赖 <code>网络协议库</code>;</li>
<li><code>网络协议库</code>,又依赖 <code>数据加密库</code>。</li>
</ul>
<h1 id="疑问">疑问</h1>
<p>小白灵魂拷问:<strong><code>我为什么不能把所有代码复制粘贴,揉进一个 .py 文件里?</code></strong></p>
<p>这是 99% 的新手都会踩的坑,我结合​<strong>嵌入式开发实际工作</strong>​,告诉你绝对不能这么做的 4 个核心原因:</p>
<ol>
<li>依赖库会​<strong>版本升级</strong>​,合并后彻底无法更新</li>
</ol>
<ul>
<li><code>max30102.py</code> 驱动:作者会修复 bug、优化读取精度、升级硬件适配</li>
<li><code>filter_lib.py</code> 算法:作者会优化滤波效果,降低误差</li>
<li>如果你把所有代码合并成一个文件:<br>
每次依赖库升级,你都要把整个大文件重写一遍,极易改错、删错代码;而​<strong>分离成独立依赖库</strong>​,只需要升级单个文件,主代码完全不用动。</li>
</ul>
<ol start="2">
<li>依赖库是​<strong>通用工具</strong>​,可以复用到无数项目</li>
</ol>
<ul>
<li><code>max30102</code> 驱动:不仅能做心率,还能做血氧、手势检测</li>
<li><code>滤波算法库</code>:不仅能给心率用,还能给温湿度、气压传感器用</li>
<li>合并成一个文件后,代码彻底「锁死」在心率项目里,无法复用;<br>
独立依赖库,所有项目直接调用,一次编写,无数次使用。</li>
</ul>
<ol start="3">
<li>嵌套依赖会让代码<strong>彻底失控</strong></li>
</ol>
<p>一个心率功能,可能依赖 2 个库;这 2 个库,又各自依赖 2 个底层库;最终依赖关系会变成:主代码 → 4 个依赖库。如果全部合并成一个文件,代码会达到​<strong>几千行、几万行</strong>​,报错了根本找不到问题在哪。</p>
<ol start="4">
<li>开发维护<strong>成本爆炸</strong></li>
</ol>
<p>嵌入式开发大多是多人协作:A 工程师写传感器驱动,B 工程师写算法,C 工程师写主功能。代码分开(依赖库模式),大家互不干扰;合并成一个文件,所有人改同一个文件,直接冲突、代码报废。</p>
<p>这就是为什么,我们必须给 ESP32 实现:<br>
<strong>类 Python pip 的 在线自动安装 + 依赖自动加载</strong>:一行代码,自动装主库 + 所有依赖库 + 嵌套依赖,自动处理版本升级!</p>
<h1 id="核心方案upypi--mip">核心方案:uPyPi + mip</h1>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170708751-257242962.png"></p>
<p>我们做的 uPyPi,就是 MicroPython 生态的​<strong>PyPI(Python 官方包仓库)</strong>​,配合 MicroPython 官方内置的 <code>mip</code>(<code>mip installs packages</code>)工具,实现:</p>
<ul>
<li>✅ ​<strong>包托管</strong>​:驱动包、工具包一键上传到 uPyPi,全球开发者可访问</li>
<li>✅ ​<strong>一键安装</strong>​:开发板连网,一行代码安装主包 + 所有依赖</li>
<li>✅ ​<strong>依赖自动管理</strong>​:<code>mip</code> 自动递归安装声明的依赖包,无需手动操作</li>
<li>✅ ​<strong>全芯片兼容</strong>​:纯软件包设计,支持所有 MicroPython 开发板,无硬件耦合</li>
<li>✅ ​<strong>版本管理</strong>​:语义化版本控制,彻底避免版本冲突</li>
</ul>
<h1 id="从零实操3-步实现-esp32-动态安装依赖">从零实操:3 步实现 ESP32 动态安装依赖</h1>
<blockquote>
<p>关于如何下载上传驱动包可看wiki: https://freakstudio.cn/node/019c992e-2994-7180-b570-12199db1a7cb<br>
<img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170719091-2022953107.png"></p>
</blockquote>
<h2 id="第一步制作第三方依赖包-math_utils">第一步:制作第三方依赖包 <code>math_utils</code></h2>
<p>这是一个纯软件工具包,无任何硬件代码,作为主包的依赖。</p>
<p>文件夹结构如下:<br>
<img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170707935-928544767.png"></p>
<p><code>code/math_utils.py </code>代码如下:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170707921-1476790198.png"></p>
<p>package.json 完整配置为:</p>
<pre><code>{
"name": "math_utils",
"version": "1.0.1",
"description": "纯第三方软件依赖包(无硬件,测试用)",
"author": "test",
"license": "MIT",
"chips": "all",
"fw": "all",
"_comments": {
    "chips": "该包支持运行的芯片型号,all表示无芯片限制",
    "fw": "该包依赖的特定固件如ulab、lvgl,all表示无固件依赖"
},
"urls": [
    [
      "math_utils.py",
      "code/math_utils.py"
    ]
]
}
</code></pre>
<p>打包文件夹,上传到 uPyPi 平台,获取包地址:<br>
<img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170712713-1146299739.png"></p>
<h2 id="第二步制作主测试包-test_core">第二步:制作主测试包 <code>test_core</code></h2>
<p>主包依赖上面的 <code>math_utils</code>,用户只需要安装主包,<code>mip</code> 自动安装依赖。<br>
文件夹结构:<br>
<img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170707931-1494455469.png"></p>
<p>code/test_core.py 代码如下:<br>
<img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170707728-516080840.png"></p>
<p>package.json 完整配置为:</p>
<pre><code class="language-{">"name": "test_core",
"version": "1.0.4",
"description": "纯软件测试主包(无硬件,依赖第三方包)",
"author": "test",
"license": "MIT",
"chips": "all",
"fw": "all",
"_comments": {
    "chips": "该包支持运行的芯片型号,all表示无芯片限制",
    "fw": "该包依赖的特定固件如ulab、lvgl,all表示无固件依赖"
},
"urls": [
    [
      "test_core.py",
      "code/test_core.py"
    ]
],
"deps": [
    ["https://upypi.net/pkgs/math_utils/1.0.1", "latest"]
]
}
</code></pre>
<p>这里,我们在<code>deps</code>字段声明主包依赖 <code>math_utils</code> 的 uPyPi 地址,<code>mip</code> 安装主包时,​<strong>自动递归安装依赖包</strong>​,用户完全不用管;`支持多个依赖,可嵌套依赖,mip自动处理所有依赖链。</p>
<p>打包文件夹,上传到 uPyPi 平台,获取主包地址:</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170713466-1308746287.png"></p>
<h2 id="第三步esp32-一键安装--测试">第三步:ESP32 一键安装 + 测试</h2>
<p>ESP32 完整代码如下:</p>
<pre><code># ==================== ESP32 纯软件测试(无硬件、无耦合) ====================
import time
import network
import mip

# ==================== 配置 ====================
WIFI_SSID = "808"
WIFI_PASSWORD = "88888888"
# uPyPi 主测试包地址(替换成upypi的地址)
MAIN_PACKAGE = "https://upypi.net/pkgs/test_core/1.0.4"

# ==================== 连接WiFi ====================
def connect():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    print("连接WiFi...")
    wlan.connect(WIFI_SSID, WIFI_PASSWORD)
    for _ in range(10):
      if wlan.isconnected():
            print("WiFi 连接成功!IP:", wlan.ifconfig())
            return True
      time.sleep(1)
    print("WiFi 连接失败")
    return False

# ==================== 远程安装(自动装第三方软件依赖) ====================
def install():
    print("开始安装:主包 + 第三方纯软件依赖...")
    mip.install(MAIN_PACKAGE)
    print("✅ 安装完成!无任何硬件依赖")

# ==================== 纯软件测试(无硬件) ====================
def test():
    # 导入安装好的纯软件包
    from test_core import TestCore
    test = TestCore()
   
    # 运行测试
    print("\n===== 纯软件测试结果 =====")
    print(test.test_add(10, 20))
    print(test.test_multiply(10, 20))
    print("=========================\n")
    print("🎉 测试成功!依赖安装正常")

# ==================== 主程序 ====================
if __name__ == "__main__":
    if connect():
      install()
      test()
</code></pre>
<p>运行结果如下:<img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170709645-2098227901.png"></p>
<p>我们也可以使用本地安装方式:<br>
<img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170707944-2025864504.png"></p>
<p>可以看到:ESP32 成功通过 MicroPython 的 <code>mip</code> 工具实现了类 Python <code>pip</code> 的在线动态安装能力,设备连接 WiFi 后自动拉取并部署了主测试包 <code>test_core.py</code> 及其第三方依赖包 <code>math_utils.py</code> 到 <code>/lib</code> 目录。<br>
后续纯软件测试验证了主包对依赖库的正常调用,加法、乘法运算结果完全正确,完整实现了嵌入式设备端的在线库安装、依赖自动管理与功能验证,彻底解决了传统手动拷贝文件、漏装依赖的开发痛点,实现了与 PC 端 Python 开发一致的标准化包管理体验。</p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170708751-257242962.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/2591203/202604/2591203-20260404170728051-49225026.png"></p><br><br>
来源:https://www.cnblogs.com/FreakEmbedded/p/19821479
頁: [1]
查看完整版本: ESP32 实现在线动态安装库和自动依赖安装-使用uPyPI包管理平台