4、脚本语言实战:Python 在嵌入式自动化中的角色(paramiko、os、subprocess)

说实话,很多做嵌入式的兄弟对 Python 有点偏见。

觉得它慢,觉得它不靠谱,觉得「真干活还得靠 C」。
嗯,我当年也是这么想的。直到有一次,我需要给 50 块开发板烧录固件、修改配置、跑测试用例……
手动搞了一整天,还漏了两块。从那以后,我彻底服了。

Python 在嵌入式自动化里,不是来替代 C 的。
它是来当「工头」的。C 是搬砖的,Python 是那个拿着图纸、喊着号子、检查质量的人。

4.1 为什么是 Python?

你想想看,嵌入式自动化最常干的事是什么?

  • 批量操作文件(复制、改名、解压)
  • 执行系统命令(编译、烧录、重启)
  • 远程登录设备(SSH 上去改参数、看日志)
  • 解析日志、生成报告

这些事,用 C 写一遍,编译、调试、烧录……黄花菜都凉了。
Python 的优势就在于:开发快、改起来快、粘合能力强

核心观点:Python 是嵌入式自动化的「胶水语言」。它不负责底层性能,它负责把各个工具、设备、流程串起来。

4.2 os 模块:跟操作系统打交道

os 模块是我用得最多的。说白了,它就是 Python 和操作系统之间的翻译官。

常用场景:

  • 遍历文件夹,找所有 .hex 文件
  • 创建/删除目录,整理构建产物
  • 获取环境变量,判断当前是 Windows 还是 Linux
import os

# 获取当前工作目录
cwd = os.getcwd()
print(f"当前目录: {cwd}")

# 列出所有 .bin 文件
for file in os.listdir("."):
    if file.endswith(".bin"):
        print(f"找到固件: {file}")

# 创建输出目录
output_dir = "build_output"
if not os.path.exists(output_dir):
    os.makedirs(output_dir)
    print(f"已创建目录: {output_dir}")
我的习惯:os.path.join() 拼接路径,别自己加斜杠。Windows 和 Linux 的路径分隔符不一样,这个函数会自动处理。

4.3 subprocess 模块:执行外部命令

这是自动化的核心。你要在脚本里调用编译器、烧录工具、测试程序……都得靠它。

os.system() 也能执行命令,但我个人强烈建议用 subprocess
为什么?因为 os.system() 拿不到输出结果,出了问题你都不知道错在哪。

import subprocess

# 执行编译命令,并获取输出
result = subprocess.run(
    ["make", "clean", "all"],
    capture_output=True,
    text=True,
    cwd="/home/project/firmware"
)

if result.returncode == 0:
    print("编译成功!")
    print(result.stdout[-200:])  # 只看最后 200 个字符
else:
    print("编译失败!")
    print(result.stderr)

避坑指南:

  • capture_output=True 捕获输出,别用 shell=True(有安全风险)
  • 超时处理:加 timeout=60,防止命令卡死
  • 检查返回值:returncode != 0 就是出错了
我曾经踩过的坑:有一次用 shell=True 执行一条带参数的命令,参数里有个文件名包含空格,结果命令被截断了,烧录了错误的固件。从那以后,我坚持用列表传参。

4.4 paramiko:远程操作设备

很多嵌入式设备跑的是 Linux,你没法直接插键盘鼠标。
SSH 就是你的手和眼睛。paramiko 是 Python 里最成熟的 SSH 库。

典型场景:

  • 批量登录 10 台设备,检查版本号
  • 远程执行测试脚本,收集结果
  • 上传新固件,远程重启
import paramiko

def ssh_execute(host, port, username, password, command):
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    
    try:
        client.connect(host, port=port, username=username, password=password, timeout=10)
        stdin, stdout, stderr = client.exec_command(command)
        
        output = stdout.read().decode('utf-8')
        error = stderr.read().decode('utf-8')
        
        return output if output else error
    except Exception as e:
        return f"连接失败: {str(e)}"
    finally:
        client.close()

# 批量检查设备状态
devices = ["192.168.1.101", "192.168.1.102", "192.168.1.103"]
for ip in devices:
    result = ssh_execute(ip, 22, "root", "admin123", "uname -a")
    print(f"{ip}: {result[:50]}...")
实用技巧:生产环境中别硬编码密码。用 paramiko.RSAKey 做密钥登录,或者从环境变量读取密码。

4.5 三个模块的配合实战

光讲单个模块没意思。我给你看一个我实际用过的自动化流程:

  1. os 模块:扫描本地目录,找到最新的固件文件
  2. paramiko:SSH 登录到 5 台测试设备
  3. subprocess:在本地执行烧录工具,把固件通过 TFTP 推送到设备
  4. paramiko:远程执行重启命令,检查设备是否正常启动
  5. os + subprocess:收集日志,生成测试报告
import os
import subprocess
import paramiko
from datetime import datetime

def auto_deploy():
    # 1. 找最新的固件
    firmware_dir = "/home/build/output"
    files = [f for f in os.listdir(firmware_dir) if f.endswith(".bin")]
    latest = max(files, key=lambda f: os.path.getmtime(os.path.join(firmware_dir, f)))
    print(f"最新固件: {latest}")
    
    # 2. 部署到设备
    devices = ["192.168.1.201", "192.168.1.202"]
    for ip in devices:
        print(f"正在部署到 {ip}...")
        
        # 用 subprocess 调用 tftp 推送固件
        subprocess.run(["tftp", ip, "-c", "put", latest], check=True)
        
        # 用 paramiko 远程重启
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(ip, username="root", password="admin")
        ssh.exec_command("flashcp /tmp/firmware.bin /dev/mtd5 && reboot")
        ssh.close()
        
        print(f"{ip} 部署完成,已重启")
    
    print(f"部署完成,时间: {datetime.now()}")

if __name__ == "__main__":
    auto_deploy()

4.6 总结与建议

模块 核心用途 我的建议
os 文件操作、路径处理 多用 os.path,少自己拼字符串
subprocess 执行外部命令 用 run() 别用 system(),加超时
paramiko 远程 SSH 操作 用密钥登录,别硬编码密码

说实话,这三个模块学会了,你就能搞定 80% 的嵌入式自动化场景。
剩下的 20%,无非是加个日志、做个界面、或者对接数据库——那是锦上添花的事。

我见过太多人,明明每天重复做着同样的事,却不愿意花半天写个脚本。
嗯,如果你也是这样的,今天就开始吧。
从「自动编译」开始,到「自动部署」,再到「自动测试」——
你会发现,原来每天能多出两小时喝咖啡。