前面Python基础过了一遍,今天聊文件和数据处理的实操内容。

机器人开发中经常要和三类文件打交道:CSV格式的传感器日志、JSON格式的配置文件和通信数据、YAML格式的ROS2参数文件。这三种格式的读写是基本功,面试的时候经常被问到。

先说个真实场景。

老板跑过来跟你说:"昨天跑了一晚上的实验,数据都在那个CSV里,你帮我分析一下成功率。"你打开文件一看,几万行数据,每行是时间戳、物体ID、抓取姿态、成功/失败。手动看?不可能。用Excel打开?卡死了。

这时候Python就派上用场了。几十行代码,读取、分析、出图,一气呵成。

CSV:传感器日志的标准格式

CSV是最简单的表格数据格式。Python内置了csv模块:

import csv

# 读取
with open("grasp_log.csv", "r") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row["object_id"], row["success"])

# 写入
with open("results.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["object_id", "success", "time"])
    writer.writerow(["cup", "True", "2026-07-09 14:30:00"])

DictReader比普通的reader好用——它自动把第一行当列名,每行数据返回一个dict,用列名访问,比用索引清晰得多。

实际项目中,CSV文件经常有编码问题。中文路径、中文注释在Windows上特别容易出问题。建议统一用UTF-8编码:

with open("data.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)

如果数据量大(几百万行),csv模块会比较慢。这时候可以上pandas,后面会专门讲。

JSON:通信和配置的标准格式

JSON是机器人系统中最常见的数据交换格式。ROS2的很多接口、API的返回值、配置文件都用JSON。

Python处理JSON非常简单:

import json

# 读取
with open("config.json", "r") as f:
    config = json.load(f)

# 写入
config["max_speed"] = 1.5
with open("config.json", "w") as f:
    json.dump(config, f, indent=2)

# 字符串和对象之间转换
json_str = json.dumps(config, ensure_ascii=False)
obj = json.loads(json_str)

indent=2让输出格式化,方便阅读。ensure_ascii=False让中文正常显示而不是变成Unicode转义。

一个容易踩的坑:JSON的key必须是字符串。如果你的dict用了int或tuple做key,json.dump会报错。解决方法是在序列化之前把key转成字符串。

还有一个实用的技巧:处理嵌套JSON时,用json.loads配合递归提取需要的字段:

def extract_field(data, field, default=None):
    """从嵌套dict中安全地提取字段"""
    keys = field.split(".")
    for key in keys:
        if isinstance(data, dict):
            data = data.get(key, default)
        else:
            return default
    return data

# 用法
speed = extract_field(response, "robot.status.max_speed", 0.0)

YAML:ROS2的配置语言

如果你用ROS2,YAML是绕不过去的。ROS2的参数文件、Launch文件中的参数配置,都是YAML格式。

Python处理YAML需要安装PyYAML库:pip install pyyaml。

import yaml

# 读取
with open("params.yaml", "r") as f:
    params = yaml.safe_load(f)

# 写入
with open("output.yaml", "w") as f:
    yaml.dump(params, f, default_flow_style=False)

注意一定要用yaml.safe_load而不是yaml.load。后者有安全风险——恶意的YAML文件可以执行任意Python代码。safe_load限制了可反序列化的类型,避免了这个问题。

一个典型的ROS2参数YAML文件长这样:

lidar_node:
  ros__parameters:
    scan_range: 30.0
    scan_freq: 10
    port: "/dev/ttyUSB0"

读取后就是一个嵌套dict:params["lidar_node"]["ros__parameters"]["scan_range"]。

路径处理:os.path vs pathlib

处理文件路径,Python有两个选择:传统的os.path和现代的pathlib。推荐用pathlib——它是面向对象的,用起来更直观:

from pathlib import Path

# 拼接路径
data_dir = Path("/home/user/robot_data")
log_file = data_dir / "logs" / "scan_001.csv"

# 检查文件是否存在
if log_file.exists():
    print(f"File size: {log_file.stat().st_size} bytes")

# 遍历目录下所有CSV文件
for csv_file in data_dir.glob("**/*.csv"):
    print(csv_file.name)

# 读取文件内容
lines = log_file.read_text().splitlines()

pathlib的/运算符用来拼接路径,glob支持递归搜索,read_text和write_text一行搞定文件读写。比os.path那一堆字符串操作优雅太多。

大文件处理的注意事项

当CSV文件超过百万行的时候,csv模块会变得很慢。这时候有两个选择:一是用pandas的read_csv,它底层是C实现,速度快很多;二是用生成器逐行读取,避免一次性把整个文件加载到内存。

# 生成器方式:内存友好
def read_large_csv(filepath):
    with open(filepath, "r", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for row in reader:
            yield row  # 每次只返回一行

# 使用
for row in read_large_csv("million_rows.csv"):
    process(row)

还有一个常见坑:写入CSV时忘记加newline=""参数,在Windows上会多出空行。加上newline=""让csv模块自己控制换行,就不会出这个问题。

补充一个实际工作中经常遇到的场景:解析机器人日志文件。很多硬件设备输出的日志格式不是标准的CSV或JSON,而是自定义的文本格式。这时候需要用正则表达式配合文件处理来提取数据。Python的re模块非常强大,建议花点时间熟悉常用的正则语法,在实际工作中这个技能特别实用。

给正在准备面试的你

文件处理在面试中不算高频考点,但在实际工作中是每天都要用的。建议你把CSV、JSON、YAML的读写都练一遍,特别是pathlib的使用。面试的时候如果聊到数据处理,能自然地提到这些工具,说明你有实际项目经验。

下篇进入NumPy的世界——机器人数据处理的Python标配。NumPy是Python科学计算的基石,做矩阵运算、处理传感器数据、跑深度学习模型,都离不开它。


如果这篇文章对你有帮助,欢迎点赞、在看、转发三连。 你的支持是我持续更新的最大动力。

「机器人软件开发面试·从入门到精通」连载系列 上一篇:第69篇 Python面向对象——和C++的对比理解 下一篇预告:第71篇 NumPy入门——机器人数据处理的Python标配

有任何问题欢迎评论区留言,我会尽量回复。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐