求助:如何实现Python函数每次调用读取CSV文件单行数据
解决Pandas逐行读取CSV并每次返回单行的问题
嘿,我来帮你搞定这个问题!你的代码现在有两个核心问题导致不符合预期:
- 每次调用函数都会重置计数器并重新读文件:你在
readCsv()里把i初始化为0,而且每次调用都重新读取整个CSV,所以不管循环多少次,你拿到的都是从第0行开始的所有数据,而不是下一行。 - 取数方式不对:
data.iloc[i:,0]这种写法是获取从第i行到最后一行的整列数据(返回的是Pandas的Series对象),不是单行的单个值。
下面给你两种简单易懂的解决方案,适合Python和Pandas新手:
方案一:使用生成器函数(推荐)
生成器是Python里处理逐行迭代的绝佳工具,它只会读取一次CSV,然后每次调用返回下一行数据,非常高效:
import pandas as pd import time def read_csv_generator(file_path): # 只读取一次CSV文件,避免重复IO操作 data = pd.read_csv(file_path) # 遍历DataFrame的每一行 for _, row in data.iterrows(): # 返回当前行的5列数据 yield row[0], row[1], row[2], row[3], row[4] # 创建生成器实例,此时已经完成文件读取 csv_reader = read_csv_generator("/home/oztron/Documents/energylogger2.csv") while True: try: # 每次获取下一行数据 t, e, p, v, c = next(csv_reader) print(t) time.sleep(10) except StopIteration: # 当所有行都读完时,捕获停止迭代的异常 print("所有CSV数据已读取完毕,退出循环") break
代码说明:
read_csv_generator是一个生成器函数,用yield关键字返回数据,每次调用next()时才会执行到下一个yield。iterrows()会遍历DataFrame的每一行,返回行索引和行数据(我们用_忽略索引)。- 当所有行都读完后,生成器会抛出
StopIteration异常,我们捕获它来结束循环。
方案二:使用闭包保存状态
如果你觉得生成器有点抽象,也可以用闭包来保存计数器和已读取的CSV数据,这样每次调用读取函数时,计数器会持续递增:
import pandas as pd import time def create_csv_reader(file_path): # 一次性读取整个CSV data = pd.read_csv(file_path) row_index = 0 total_rows = len(data) def read_single_row(): nonlocal row_index # 检查是否已经读完所有行 if row_index >= total_rows: return None # 获取当前行的单个值(注意用iloc[i, col],不是i:) t = data.iloc[row_index, 0] e = data.iloc[row_index, 1] p = data.iloc[row_index, 2] v = data.iloc[row_index, 3] c = data.iloc[row_index, 4] # 计数器递增 row_index += 1 return t, e, p, v, c return read_single_row # 创建读取函数,此时已经加载了CSV数据 read_csv = create_csv_reader("/home/oztron/Documents/energylogger2.csv") while True: row_data = read_csv() if row_data is None: print("所有数据已读取完成") break t, e, p, v, c = row_data print(t) time.sleep(10)
代码说明:
create_csv_reader是一个外部函数,负责读取CSV并初始化计数器,然后返回内部函数read_single_row。nonlocal关键字让内部函数可以修改外部函数的row_index变量,避免每次调用都重置计数器。data.iloc[row_index, 0]是获取第row_index行第0列的单个值,这才是你需要的单行单个数据。
为什么你的原代码sleep生效了但看起来不对?
其实你的time.sleep(10)是生效的,但因为每次调用readCsv()都重新读取文件并从第0行开始返回所有行,所以你每次打印的都是整个第一列的Series,看起来像是重复输出,导致你误以为sleep没起作用。
内容的提问来源于stack exchange,提问作者Prayuktibid
相关产品推荐
相关产品推荐

