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 三个模块的配合实战
光讲单个模块没意思。我给你看一个我实际用过的自动化流程:
- os 模块:扫描本地目录,找到最新的固件文件
- paramiko:SSH 登录到 5 台测试设备
- subprocess:在本地执行烧录工具,把固件通过 TFTP 推送到设备
- paramiko:远程执行重启命令,检查设备是否正常启动
- 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%,无非是加个日志、做个界面、或者对接数据库——那是锦上添花的事。
我见过太多人,明明每天重复做着同样的事,却不愿意花半天写个脚本。
嗯,如果你也是这样的,今天就开始吧。
从「自动编译」开始,到「自动部署」,再到「自动测试」——
你会发现,原来每天能多出两小时喝咖啡。