You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python写入CSV文件为空无报错,请求问题排查帮助

问题分析与修复方案

1. 核心问题:未收集全必要数据就写入CSV,变量未初始化

你的代码在每次循环中都会尝试调用position函数并写入CSV,但此时D1、D2、D3可能还没全部从串口获取到有效值,甚至程序刚启动时这些变量根本没被定义。这会导致两种情况:

  • 若串口还未返回对应数据,listeDonnees可能为空列表,访问listeDonnees[2]会触发IndexError(如果程序没崩溃,大概率是你没看到报错,或串口一直有数据但未覆盖三个变量)
  • 即使没报错,写入CSV的也是未初始化的变量值或错误计算结果,若程序因报错终止,CSV文件只会保留表头,后续内容无法写入

2. 次要问题:文件频繁打开关闭的性能隐患

每次循环都打开/关闭CSV文件,虽语法合法,但会带来不必要的性能开销,建议在循环外保持文件打开状态,或仅在获取完整数据时写入。

3. 潜在问题:串口函数鲁棒性不足

recup_port_Arduino函数中,如果遍历串口时没找到包含COM9的端口,mData变量未定义就执行print(mData.is_open),会直接报错。


修复后的代码

import serial
import serial.tools.list_ports
import numpy as np
import csv

header1 = "x_value"
header2 = "y_value"
header3 = "z_value"
fieldnames = [header1, header2, header3]

# 初始化变量,避免未定义报错
D1 = D2 = D3 = None

def recup_port_Arduino():
    ports = list(serial.tools.list_ports.comports())
    mData = None
    for p in ports:
        print(p)
        if 'COM9' in p.description:
            mData = serial.Serial(p.device, 115200)
            break  # 找到目标串口后立即退出循环
    if not mData:
        raise Exception("未找到Arduino串口COM9")
    print(mData.is_open)
    print(mData.name)
    return mData

def position(D1,D2,D3,y2,x3):
    y = -(D2**2 - D1**2 - y2**2)/(2*y2)
    x = -(D3**2 - D1**2 - x3**2)/(2*x3)
    z = np.sqrt(D1**2 - x**2 - y**2)
    return x,y,z

Data = recup_port_Arduino()

# 在循环外打开CSV文件,保持打开状态直到程序终止
with open('Position.csv', 'w', newline='') as csv_file:
    csv_writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
    csv_writer.writeheader()
    
    while True:
        line1 = Data.readline()
        if not line1:
            continue  # 跳过空行
        listeDonnees = line1.split()
        # 先判断列表长度,避免索引越界
        if len(listeDonnees) < 3:
            continue
        
        try:
            if listeDonnees[2] == b'2':
                if len(listeDonnees) >=5:
                    D2 = float(listeDonnees[4].decode())
                    print(f'D2 = {D2}')
            elif listeDonnees[2] == b'3':
                if len(listeDonnees) >=5:
                    D3 = float(listeDonnees[4].decode())
                    print(f'D3 = {D3}')
            elif listeDonnees[2] == b'm':
                if len(listeDonnees) >=2:
                    D1 = float(listeDonnees[1].decode())
                    print(f'D1 = {D1}')
        except (ValueError, IndexError):
            print("串口数据格式错误,跳过当前行")
            continue
        
        # 只有当三个变量都获取到有效值时,才计算并写入CSV
        if all(v is not None for v in [D1, D2, D3]):
            try:
                x_value, y_value, z_value = position(D1, D2, D3, 0.75, 0.75)
                info = {
                    header1: x_value,
                    header2: y_value,
                    header3: z_value
                }
                csv_writer.writerow(info)
                csv_file.flush()  # 立即刷新缓冲区,确保数据写入磁盘
                print(x_value, y_value, z_value)
            except ValueError as e:
                print(f"计算位置时出错:{e}")

关键修复点说明

  • 变量初始化:提前将D1/D2/D3设为None,避免未定义报错
  • 数据完整性判断:仅当三个变量都有有效值时,才执行计算和写入操作
  • 鲁棒性处理:增加列表长度判断、异常捕获,避免串口数据格式错误导致程序崩溃
  • 文件操作优化:在循环外打开CSV文件,每次写入后手动刷新缓冲区,确保数据及时写入磁盘
  • 串口函数修复:增加mData空值判断,避免未找到串口时直接报错

内容的提问来源于stack exchange,提问作者Herisfal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 02:45:05