1. MATLAB与Python环境互操作与数据交换
任务拆解:一条 CSV 数据从磁盘到 MATLAB 图窗的完整链路
本例要验证的不是“MATLAB 能不能调用 Python”,而是数据在两种语言之间往返时是否保持类型、形状和数值一致。整条链路包含四个关键交接点:MATLAB 向 Python 传递文件路径、Python 读取并计算、Python 结果转换为 MATLAB 可识别的类型、MATLAB 绘图验证。任何一个交接点出错,最终图形都会表现为空图、维度错误或数值异常。
环境准备与版本约束
MATLAB 从 R2014b 起支持 py. 接口,但不同版本对 Python 的支持范围不同。执行前先确认当前 MATLAB 绑定的 Python 版本,避免出现“找不到模块”或“解释器不兼容”的错误。
% 查看 MATLAB 当前使用的 Python 解释器
pyenv
% 若未配置,可指定 Python 路径(示例路径需按本机实际修改)
pyenv('Version', 'C:\Python311\python.exe');
% 验证基本调用
py.sys.version
Python 侧需要 numpy。若 MATLAB 绑定的解释器没有该包,可在系统命令行中执行 python -m pip install numpy,安装到同一个解释器环境。
Python 侧:编写可被 MATLAB 调用的分析脚本
MATLAB 调用 Python 时,函数必须位于 Python 的搜索路径上。最稳妥的做法是把脚本放在当前 MATLAB 工作目录,并在调用前把该目录加入 Python 路径。下面这个脚本读取两列 CSV(时间、数值),对数值列做 5 点滑动平均,返回平滑后的数组。
# analyze_csv.py
import numpy as np
def analyze_csv(path, window=5):
"""读取两列 CSV,对第二列做滑动平均,返回平滑结果。"""
data = np.loadtxt(path, delimiter=",", skiprows=1)
t = data[:, 0]
v = data[:, 1]
kernel = np.ones(window) / window
smooth = np.convolve(v, kernel, mode="same")
return smooth
注意 mode="same" 使输出长度与输入一致,这样 MATLAB 侧可以直接用同一组时间轴绘图,不需要额外对齐长度。
MATLAB 侧:调用、转换与绘图
核心操作分三步:把工作目录加入 Python 路径、调用函数、把返回的 py.numpy.ndarray 转成 MATLAB 的 double 列向量。转换时用 double() 包裹,并用 reshape 或转置保证方向一致。
% 1. 让 Python 能找到脚本
pyPath = fileparts(mfilename('fullpath'));
if isempty(pyPath), pyPath = pwd; end
insert(py.sys.path, int32(0), pyPath);
% 2. 准备数据文件(示例数据,首次运行时生成)
csvFile = fullfile(pyPath, 'sensor.csv');
if ~isfile(csvFile)
t = (0:0.1:9.9)';
v = 12 + 0.8*sin(t) + 0.3*randn(size(t));
writematrix([t, v], csvFile);
end
% 3. 调用 Python 函数
pyOut = py.analyze_csv.analyze_csv(csvFile, int32(5));
% 4. 类型转换:py.ndarray → double 列向量
smooth = double(pyOut);
smooth = smooth(:);
% 5. 读取时间轴并绘图验证
raw = readmatrix(csvFile);
t = raw(:, 1);
figure;
plot(t, raw(:, 2), 'Color', [0.7 0.7 0.7], 'DisplayName', '原始数据');
hold on;
plot(t, smooth, 'b-', 'LineWidth', 1.5, 'DisplayName', 'Python 平滑结果');
xlabel('时间 t'); ylabel('数值');
legend('Location', 'best');
title('MATLAB 调用 Python 处理 CSV 并回传绘图');
py.analyze_csv.analyze_csv 报“module not found”,优先检查 insert(py.sys.path, ...) 是否执行成功,以及脚本文件名是否与模块名一致。MATLAB 的 Python 路径与系统命令行中的 sys.path 是两套独立配置。结果判读与链路验证
运行后应看到两条曲线:灰色原始数据带有随机波动,蓝色平滑曲线明显更平缓,且两者在时间轴上完全重合。若蓝色曲线为空或长度不符,按以下顺序排查:
| 现象 | 可能原因 | 验证方法 |
|---|---|---|
| 调用报 module not found | 脚本目录未加入 Python 路径 | 在 MATLAB 中执行 py.sys.path 查看是否包含工作目录 |
| 返回类型为 py.numpy.ndarray 无法直接绘图 | 未做 double() 转换 | class(pyOut) 与 class(smooth) 对比 |
| 绘图维度不匹配 | 返回行向量而时间轴为列向量 | 用 size(smooth) 与 size(t) 检查,必要时 smooth(:) |
| 曲线数值异常偏大或偏小 | CSV 分隔符或跳过行数设置错误 | 用 readmatrix 读同一文件对比首行数值 |
可复用的验证脚本片段
把链路验证固化成一段可重复执行的检查代码,每次修改 Python 脚本后先跑它,比直接看图更快定位问题。
% 链路自检:类型、形状、数值范围
assert(isa(pyOut, 'py.numpy.ndarray'), '返回值不是 ndarray');
assert(numel(smooth) == size(raw, 1), '长度与原始数据不一致');
assert(all(isfinite(smooth)), '存在 NaN 或 Inf');
fprintf('链路正常:%d 个点,范围 [%.3f, %.3f]\n', ...
numel(smooth), min(smooth), max(smooth));
这段自检覆盖了跨语言交换中最常见的三类失败:类型未转换、形状不一致、数值非法。通过后再绘图,可以把“图不对”的问题缩小到绘图参数本身,而不是数据链路。