CSV 文件在连续追加文件时直到脚本终止才更新
CSV file not updating until script is terminated when continuously appending file
我最近开始了一个项目,为我的 Raspberry Pi 制作数据记录脚本。我的目标是制作一个程序可以:
- 从连接到我的 Pi 的 pH 传感器收集电压数据(这是
getData()
功能)。
- 在屏幕上实时绘制。
- 每隔几秒将它们连续追加到 CSV 文件中。
我在下面包含了我的代码,用于收集传感器数据的函数和 plots/saves 它们的函数。一切都按预期工作,除了某些原因,我无法看到添加到 CSV 文件 test2.csv
的新数据,直到我使用 Ctrl+C 终止代码(IDE 是 Thonny)。
虽然代码是 运行ning,但 csv 文件只是空白,甚至标题 "Data and Time, P0, P1" 都没有,让我觉得出于某种原因 Python 没有实际上,直到最后才将新数据附加到文件中。
如果我使用 Thonny 的红色 "Stop/Restart Backend" 按钮停止脚本,则不会向 test2.csv
添加新数据。如果我 运行 脚本 和 使用 Ctrl+C 停止它,新数据将仅附加到 test2.csv
,这没有帮助,因为我希望能够在不停止程序的情况下访问现有数据。
知道如何解决这个问题,以便在我不终止脚本的情况下更新 CSV 文件吗?
我收集数据的函数:
def getData():
import board
import busio
i2c = busio.I2C(board.SCL, board.SDA)
#import board module (ADS1115)
import adafruit_ads1x15.ads1115 as ADS
#import ADS1x15 library's version of AnalogIn
from adafruit_ads1x15.analog_in import AnalogIn
#create ADS object
ads = ADS.ADS1115(i2c)
ads.gain = 2/3
#single ended mode read for pin 0 and 1
chan = AnalogIn(ads, ADS.P0)
chan1 = AnalogIn(ads, ADS.P1)
return chan.voltage, chan1.voltage
这是实际绘制和保存数据的部分(可能还有哪里出错了)
importing/initializing for plotting/saving
def DataLogger(file_name):
#importing data from other function
from getData import getData
#importing/initializing for plotting/saving
import matplotlib.pyplot as plt
from time import sleep
import csv
plt.ion()
voltage_list = []
voltage1_list = []
t = []
ii = 0
print("{:>5}\t{:>5}".format('P0','P1'))
#create subplots and set axis
fig, (ax1, ax2) = plt.subplots(2)
fig.suptitle('Aquaponic Sensors')
ax1.set_ylabel('pH (V)')
ax1.set_ylim([2,4])
ax2.set_ylabel('Temperature Voltage (V)')
ax2.set_ylim([0,5])
ax2.set_xlabel('Time (s)')
#import date and time for timestamp
from datetime import datetime
#clear csv file on flash drive
loc = "/media/pi/68D2-7E93/" + file_name
f = open(loc, "w")
f.truncate()
f.close()
#save data into test.csv on flash drive by appending new row
with open(loc,'a+',newline='') as file:
writer = csv.writer(file)
writer.writerow(["Date and Time","P0 (V)", "P1 (V)"])
#define output of both channels
while True:
voltage = round(getData()[0], 3)
voltage1 = round(getData()[1], 3)
print("{:>5}\t{:>5}".format(voltage, voltage1)) #could remove
#append new output to existing lists
voltage_list.append(voltage)
voltage1_list.append(voltage1)
t.append(ii)
ii = ii+1 #time counter
sleep(1)
#append data to csv file & plot
if ii/5 == int(ii/5):
now = datetime.now()
dt_string = now.strftime("%m/%d/%Y %H:%M:%S")
writer.writerow([dt_string, voltage, voltage1])
#plot the lists
ax1.plot(t, voltage_list, 'tab:blue')
ax2.plot(t, voltage1_list, 'tab:red')
#actually draws plot
plt.draw()
plt.pause(0.001) #some weird thing that makes the plot update, doesn't work without this pause
这是我用来运行DataLogger()
:
的文件
from DataLogger import DataLogger
DataLogger("test2.csv")
对于 运行 没有连接任何硬件的文件,您可以修改 getData 以便它只生成随机数并将其输入 DataLogger
def getData():
from random import seed
from random import random
seed(1)
chanvoltage = random()
chan1voltage = random()
return chanvoltage, chan1voltage
答案其实很简单,而且很容易重现。 Python 在您关闭打开的文件之前不会写入文件。
证明:
with open(file_name, 'w') as file:
file.write('1')
input('Press enter to continue')
file.close()
input('Press enter to continue')
with open(file_name, 'a+') as file:
file.write('2')
file.close()
input('Press enter to continue')
如果你 运行 这个,并在所有的中断处查看文件,你会发现该文件
第一个break后为空,然后变成1,再变成12.
为了解决这个问题,您偶尔应该通过 .close()
关闭打开的文件然后重新打开来保存文件。
编辑:
martineau 对我的回答进行了重要更正。在这里添加,以免其他观众复制我的错误
Python does write to files before they're closed. Files generally have an associated buffer in memory where data goes initially, and when that fills up it's actually written out to the physical file. When a file is closed, this happens before the buffer is full.
为了清除这个缓冲区,可以调用.flush()
函数,这将导致缓冲区写入物理文件。
最后,在我的示例中,我确实在第二次调用时以附加模式打开文件,而不是写入模式,这将行为从覆盖文件更改为将数据附加到末尾。
我最近开始了一个项目,为我的 Raspberry Pi 制作数据记录脚本。我的目标是制作一个程序可以:
- 从连接到我的 Pi 的 pH 传感器收集电压数据(这是
getData()
功能)。 - 在屏幕上实时绘制。
- 每隔几秒将它们连续追加到 CSV 文件中。
我在下面包含了我的代码,用于收集传感器数据的函数和 plots/saves 它们的函数。一切都按预期工作,除了某些原因,我无法看到添加到 CSV 文件 test2.csv
的新数据,直到我使用 Ctrl+C 终止代码(IDE 是 Thonny)。
虽然代码是 运行ning,但 csv 文件只是空白,甚至标题 "Data and Time, P0, P1" 都没有,让我觉得出于某种原因 Python 没有实际上,直到最后才将新数据附加到文件中。
如果我使用 Thonny 的红色 "Stop/Restart Backend" 按钮停止脚本,则不会向 test2.csv
添加新数据。如果我 运行 脚本 和 使用 Ctrl+C 停止它,新数据将仅附加到 test2.csv
,这没有帮助,因为我希望能够在不停止程序的情况下访问现有数据。
知道如何解决这个问题,以便在我不终止脚本的情况下更新 CSV 文件吗?
我收集数据的函数:
def getData():
import board
import busio
i2c = busio.I2C(board.SCL, board.SDA)
#import board module (ADS1115)
import adafruit_ads1x15.ads1115 as ADS
#import ADS1x15 library's version of AnalogIn
from adafruit_ads1x15.analog_in import AnalogIn
#create ADS object
ads = ADS.ADS1115(i2c)
ads.gain = 2/3
#single ended mode read for pin 0 and 1
chan = AnalogIn(ads, ADS.P0)
chan1 = AnalogIn(ads, ADS.P1)
return chan.voltage, chan1.voltage
这是实际绘制和保存数据的部分(可能还有哪里出错了)
importing/initializing for plotting/saving
def DataLogger(file_name):
#importing data from other function
from getData import getData
#importing/initializing for plotting/saving
import matplotlib.pyplot as plt
from time import sleep
import csv
plt.ion()
voltage_list = []
voltage1_list = []
t = []
ii = 0
print("{:>5}\t{:>5}".format('P0','P1'))
#create subplots and set axis
fig, (ax1, ax2) = plt.subplots(2)
fig.suptitle('Aquaponic Sensors')
ax1.set_ylabel('pH (V)')
ax1.set_ylim([2,4])
ax2.set_ylabel('Temperature Voltage (V)')
ax2.set_ylim([0,5])
ax2.set_xlabel('Time (s)')
#import date and time for timestamp
from datetime import datetime
#clear csv file on flash drive
loc = "/media/pi/68D2-7E93/" + file_name
f = open(loc, "w")
f.truncate()
f.close()
#save data into test.csv on flash drive by appending new row
with open(loc,'a+',newline='') as file:
writer = csv.writer(file)
writer.writerow(["Date and Time","P0 (V)", "P1 (V)"])
#define output of both channels
while True:
voltage = round(getData()[0], 3)
voltage1 = round(getData()[1], 3)
print("{:>5}\t{:>5}".format(voltage, voltage1)) #could remove
#append new output to existing lists
voltage_list.append(voltage)
voltage1_list.append(voltage1)
t.append(ii)
ii = ii+1 #time counter
sleep(1)
#append data to csv file & plot
if ii/5 == int(ii/5):
now = datetime.now()
dt_string = now.strftime("%m/%d/%Y %H:%M:%S")
writer.writerow([dt_string, voltage, voltage1])
#plot the lists
ax1.plot(t, voltage_list, 'tab:blue')
ax2.plot(t, voltage1_list, 'tab:red')
#actually draws plot
plt.draw()
plt.pause(0.001) #some weird thing that makes the plot update, doesn't work without this pause
这是我用来运行DataLogger()
:
from DataLogger import DataLogger
DataLogger("test2.csv")
对于 运行 没有连接任何硬件的文件,您可以修改 getData 以便它只生成随机数并将其输入 DataLogger
def getData():
from random import seed
from random import random
seed(1)
chanvoltage = random()
chan1voltage = random()
return chanvoltage, chan1voltage
答案其实很简单,而且很容易重现。 Python 在您关闭打开的文件之前不会写入文件。
证明:
with open(file_name, 'w') as file:
file.write('1')
input('Press enter to continue')
file.close()
input('Press enter to continue')
with open(file_name, 'a+') as file:
file.write('2')
file.close()
input('Press enter to continue')
如果你 运行 这个,并在所有的中断处查看文件,你会发现该文件 第一个break后为空,然后变成1,再变成12.
为了解决这个问题,您偶尔应该通过 .close()
关闭打开的文件然后重新打开来保存文件。
编辑:
martineau 对我的回答进行了重要更正。在这里添加,以免其他观众复制我的错误
Python does write to files before they're closed. Files generally have an associated buffer in memory where data goes initially, and when that fills up it's actually written out to the physical file. When a file is closed, this happens before the buffer is full.
为了清除这个缓冲区,可以调用.flush()
函数,这将导致缓冲区写入物理文件。
最后,在我的示例中,我确实在第二次调用时以附加模式打开文件,而不是写入模式,这将行为从覆盖文件更改为将数据附加到末尾。