Python循环中拼接变量名并将save_i数据写入CSV的问题
问题:将循环生成的元组数据写入CSV文件
我尝试把while循环中生成的save_1至save_i(i等于counter的数值)每个变量作为一行写入CSV文件,每个save变量是包含counter、blast、time_to_button_press、time_to_blast_end的元组。
编写的代码如下:
# Packages import msvcrt import time import sounddevice as sd import soundfile as sf import csv # Settings PLAY_TIME = 5 # in seconds # Sound sound_file_1 = 'C:/Users/am650/Desktop/Audio/aaa_1.mp3' sound_file_2 = 'C:/Users/am650/Desktop/Audio/aaa_2.mp3' blast_file_1, fs1 = sf.read(sound_file_1, dtype='float32') blast_file_2, fs2 = sf.read(sound_file_2, dtype='float32') # Set Up time_start = time.perf_counter() time_stop = time.perf_counter() time_elapsed = time_stop - time_start counter = 0 # Basic Logic while time_elapsed < PLAY_TIME: blast = msvcrt.getch() if blast == b'1': blast = 1 time_in = time.perf_counter() time_to_button_press = time_in - time_start sd.play(blast_file_1, device=4) status = sd.wait() time_in = time.perf_counter() time_to_blast_end = time_in - time_start counter += 1 save = "save_"+str(counter) globals()[save] = (counter, blast, time_to_button_press, time_to_blast_end) print(eval("save_"+str(counter))) if time_to_blast_end > PLAY_TIME: break elif blast == b'2': blast = 2 time_in = time.perf_counter() time_to_button_press = time_in - time_start sd.play(blast_file_2, device=4) status = sd.wait() time_in = time.perf_counter() time_to_blast_end = time_in - time_start counter += 1 save = "save_"+str(counter) globals()[save] = (counter, blast, time_to_button_press, time_to_blast_end) print(eval("save_"+str(counter))) if time_to_blast_end > PLAY_TIME: break else: print("Invalid Entry") with open('C:/Users/am650/Desktop/testdata.csv', 'w', newline='') as csvfile: datawriter = csv.writer(csvfile, delimiter=' ') for i in range(counter): datawriter.writerow(eval("save_"+str(i)))
遇到的问题:
- 原代码返回空CSV文件
- 直接写入字符串
"save_"+str(i)得到变量名而非数据 - 写入
"save_"+str(counter)则重复最后一条数据且所有元素在同一列
期望CSV每行包含四个列,分别对应save变量中的四个元素,格式如下:
1, 4, 0.5, 1 2, 2, 1.7, 2.3 3, 5, 4, 4.5
本人主要使用R语言,代码不够优雅,请求帮助解决该问题。
解决方案
1. 替换动态变量为列表存储
用globals()创建save_1、save_2这类动态变量是Python中的不良实践,不仅维护麻烦,还容易出错。直接用一个列表统一存储所有生成的元组,操作更简洁可靠。
2. 修复循环终止逻辑
原代码中time_elapsed只在初始化时计算一次,循环内未更新,会导致循环无法正确终止。需要在每次循环开始时重新计算time_elapsed并判断是否超时。
3. 修正CSV写入逻辑
用列表存储数据后,直接遍历列表写入即可,无需使用不安全的eval。同时CSV默认分隔符为逗号,无需手动设置delimiter=' '。
修改后的完整代码:
# Packages import msvcrt import time import sounddevice as sd import soundfile as sf import csv # Settings PLAY_TIME = 5 # in seconds # Sound sound_file_1 = 'C:/Users/am650/Desktop/Audio/aaa_1.mp3' sound_file_2 = 'C:/Users/am650/Desktop/Audio/aaa_2.mp3' blast_file_1, fs1 = sf.read(sound_file_1, dtype='float32') blast_file_2, fs2 = sf.read(sound_file_2, dtype='float32') # Set Up time_start = time.perf_counter() counter = 0 # 用列表存储所有数据,替代动态创建的save_1、save_2... data_list = [] # Basic Logic while True: time_elapsed = time.perf_counter() - time_start if time_elapsed >= PLAY_TIME: break blast = msvcrt.getch() if blast == b'1': blast = 1 time_in = time.perf_counter() time_to_button_press = time_in - time_start sd.play(blast_file_1, device=4) status = sd.wait() time_in = time.perf_counter() time_to_blast_end = time_in - time_start counter += 1 # 将元组添加到列表 data_tuple = (counter, blast, time_to_button_press, time_to_blast_end) data_list.append(data_tuple) print(data_tuple) if time_to_blast_end > PLAY_TIME: break elif blast == b'2': blast = 2 time_in = time.perf_counter() time_to_button_press = time_in - time_start sd.play(blast_file_2, device=4) status = sd.wait() time_in = time.perf_counter() time_to_blast_end = time_in - time_start counter += 1 data_tuple = (counter, blast, time_to_button_press, time_to_blast_end) data_list.append(data_tuple) print(data_tuple) if time_to_blast_end > PLAY_TIME: break else: print("Invalid Entry") with open('C:/Users/am650/Desktop/testdata.csv', 'w', newline='') as csvfile: # 默认分隔符是逗号,符合需求 datawriter = csv.writer(csvfile) # 遍历列表写入每一行 for row in data_list: datawriter.writerow(row)
关键修改说明
- 新增
data_list列表,每次生成数据直接append,避免动态变量的混乱 - 循环改为
while True,内部先计算time_elapsed并判断超时,确保循环能正确终止 - CSV写入时直接遍历
data_list,每个元组自动对应一行四列数据 - 移除了不安全的
eval和globals()操作,代码更简洁易维护
内容的提问来源于stack exchange,提问作者grace.cutler
相关产品推荐
相关产品推荐

