Python报错ValueError: I/O operation on closed file的原因排查及文件.close()方法使用疑问
解决 ValueError: I/O operation on closed file 错误及文件关闭方法的正确使用
错误原因分析
你碰到的ValueError: I/O operation on closed file错误,核心问题是手动提前关闭了文件,而迭代器reader还需要访问这个已关闭的文件对象。
看你的代码逻辑:在with块内部找到匹配的用户后,你调用了csvfile.close()然后return。但with语句的核心作用就是自动管理文件的生命周期——不管代码块是正常结束、遇到return还是抛出异常,它都会自动帮你关闭文件。你手动调用close()会让文件在reader迭代完成前就被强制关闭,当后续循环(哪怕只剩最后几行未处理)尝试访问文件时,就会触发这个错误。
另外,你在with块外部还额外调用了一次csvfile.close(),这完全是多余的:with块结束后,csvfile已经被自动关闭,此时再调用close()不仅没有意义,还可能引发额外的异常。
修正后的代码
只需要移除所有手动的csvfile.close()调用,让with语句自动处理文件关闭即可:
def login(): global logged_in username = input("Please enter your username: ") password = getpass.getpass(prompt="Please enter your password: ") hash_func = hashlib.sha256() encoded_pw = password.encode() hash_func.update(encoded_pw) password = hash_func.hexdigest() with open('accounts.csv', newline='') as csvfile: reader = csv.DictReader(csvfile) for row in reader: if username == row['username'] and password == row['password']: logged_in = True print(f"Welcome {username}!") return bool(logged_in) print("Username or password incorrect!") print("Please try again or create an account.") return bool(logged_in) # 补充返回值,保证函数始终有明确输出
关于close()方法的使用建议
- 绝对不要在
with块内手动调用close():with是Python处理文件的最佳实践,它会确保文件被正确关闭,完全不需要你手动干预。 - 不要在
with块外调用已被with管理的文件对象的close():此时文件已经被自动关闭,重复调用没有任何作用,反而可能导致不可预期的错误。 - 如果没有使用
with语句(不推荐这种写法),才需要在文件操作完成后手动调用close(),并且最好用try...finally块确保即使发生异常文件也能被关闭。
内容的提问来源于stack exchange,提问作者this_is_the_username




