Python写入CSV文件报ValueError: I/O operation on closed file错误
问题排查
你触发的ValueError: I/O operation on closed file报错、输出文件空白问题,是代码缩进错误+多处逻辑bug共同导致的,具体问题和修复方案如下:
核心报错原因
Python的with上下文管理器会在代码退出其缩进块时,自动关闭打开的文件对象。你的代码里,文件处理的while循环整体没有缩进在with块范围内——with块内仅执行了两次readline()操作就退出了,两个文件被自动关闭,后续循环里调用modifiedFile.write()自然会触发“操作已关闭文件”的错误,且全程没有有效写入内容,所以生成的文件是空白的。
其余代码bug
除了核心缩进问题,你的代码还有几处会导致运行异常/结果错误的问题:
calculateDelta函数定义了入参o和c,但内部完全没有使用传入参数,反而直接引用全局的closingPrice、openingPrice,还把两个价格的变量名写反,计算出的delta值完全错误。direction函数没有传入delta参数,无法拿到计算好的涨跌值;且代码中写的str(direction)是直接把函数对象转成字符串,没有加括号调用函数,最终写入文件的会是无意义的函数内存地址,不是0/1的方向值。- 文件读取逻辑错误:
with块内连续两次调用readline(),会直接跳过原文件的表头+第一行数据;且while循环内没有持续读取下一行的代码,就算缩进正确也会陷入死循环。另外你定义了输出文件的表头,但从未将表头写入新文件。 - CSV字段索引匹配错误:你定义的输出列顺序是
Date,Close,Open,Delta,Direction,但取字段时用了索引1、2、5,常规CSV第一列(索引0)为日期列,直接按现有索引取值会取错字段。
修复后可运行代码
originalFileName = 'C:/Users/Janedoe/Desktop/My Projects/tickerinfo.csv' modifiedFileName = 'C:/Users/Janedoe/Desktop/My Projects/tickerInfoWithDelta.csv' def calculateDelta(opening_price, closing_price): # 统一使用传入的参数计算,不依赖全局变量 open_val = float(opening_price) close_val = float(closing_price) return close_val - open_val def get_direction(delta_val): # 传入delta值判断涨跌方向,上涨返回1,下跌/平返回0 return 1 if delta_val > 0 else 0 with open(originalFileName, 'r', encoding='utf8') as originalFile, open(modifiedFileName, 'w', encoding='utf8') as modifiedFile: # 先写入新文件表头 modifiedFile.write('Date,Close,Open,Delta,Direction\n') # 跳过原文件的表头行 next(originalFile) # 所有文件操作逻辑全部缩进在with块内,避免文件提前关闭 for line in originalFile: line = line.strip() # 跳过空行 if not line: continue line_list = line.split(',') # 注意:以下索引需要和你原CSV的实际列位置对齐,示例默认原CSV列顺序为 日期、收盘价、开盘价 对应前3列 date = line_list[0] closing_price = line_list[1] opening_price = line_list[2] delta = calculateDelta(opening_price, closing_price) direction_val = get_direction(delta) # 拼接行内容写入 new_line = f"{date},{closing_price},{opening_price},{delta},{direction_val}\n" modifiedFile.write(new_line)
入门提醒
- Python靠缩进划分代码块归属,操作打开文件、数据库连接这类上下文资源的代码,必须放在对应
with块的缩进范围内,退出缩进就会自动释放资源。 - 定义函数时尽量通过参数传递需要的值,不要随意引用全局变量,很容易出现变量找不到、值不匹配的问题。
- 调用函数必须在函数名后加括号传参,直接写函数名不会执行函数逻辑,只会拿到函数对象本身。
内容的提问来源于stack exchange,提问作者arosesthorn
相关产品推荐
相关产品推荐

