为什么我们不能迭代python3中“with”语句范围之外的变量?

问题描述 投票:0回答:1

我对Python的学习有点陌生,所以如果有任何错误,请原谅我。

我最近了解了Python中的“with”语句以及它在安全正确地打开和关闭文件方面的相应用法。据我了解,在“with”语句块之后无法从文件中读取/写入,即所有文件的读写都必须限制在“with”语句块内。

我还读到,可以将文件的内容存储在变量中,并在“with”语句的范围之外使用这样的变量。例如,在下面的示例中,如果您要将读取 CSV 文件生成的可迭代对象存储在变量中,您仍然可以在“with”语句范围之外打印出可迭代对象:

import csv

with open('example_file.csv', 'r') as f:
    temp_var = csv.DictReader(f)

print(temp_var) # Prints out a DictReader Object containing data from the CSV file
import csv

with open('example_file.csv', 'r') as f:
    temp_var = csv.DictReader(f)

for i in temp_var:
    print(i) # Produces a 'ValueError: I/O operation on closed file.'

但是,当尝试在“with”语句范围之外迭代上面示例中的 DictReader 对象时,我们会收到一条错误消息,指出“ValueError:对已关闭文件进行 I/O 操作”。如下图

import csv

with open('example_file.csv', 'r') as f:
    temp_var = csv.DictReader(f)

for i in temp_var:
    print(i) # Produces a 'ValueError: I/O operation on closed file.'

看起来像“ValueError:对关闭的文件进行 I/O 操作”的错误。当我尝试将 DictReader 对象传递到“with”语句范围之外的函数时,似乎也会发生这种情况,如下所示:

import csv

with open('example_file.csv', 'r') as f:
    temp_var = csv.DictReader(f)

temp_list = list(temp_var) # Produces a 'ValueError: I/O operation on closed file.'

绕过“ValueError:已关闭文件上的 I/O 操作”的唯一方法。就是将迭代部分放在“with”语句的范围内,如下图

import csv

with open('example_file.csv', 'r') as f:
    temp_var = csv.DictReader(f)

for i in temp_var:
    print(i) # Produces a 'ValueError: I/O operation on closed file.'

我很好奇为什么会发生这样的错误,即为什么我们可以打印在“with”语句范围内定义的“with”语句范围之外的变量,但不能迭代它?我愿意接受有关如何克服此错误的建议。

提前感谢您。

为了解决这个问题,我搜索了为什么“with”语句会产生“ValueError:对关闭文件进行I/O操作”。我发现的只是一些答案表达,惯例是始终在“with”语句的范围内进行迭代。然而,我一直不明白为什么我们可以在“with”语句的范围之外打印变量,但在它之外进行迭代。直觉上我相信,如果他们可以在“with”语句范围之外打印变量,那么他们必须能够迭代“with”语句范围之外的变量,但必须有某种程度的解释,这必须超出我的范围

python python-3.x file-io
1个回答
1
投票

出现“ValueError:对关闭文件进行I/O操作”错误是因为,当使用with语句打开文件时,当退出with语句内的代码块时,文件会自动关闭。这样做是为了确保正确的资源管理并避免文件处理的潜在问题。

在您的示例中,当您执行以下操作时:

with open('example_file.csv', 'r') as f:
    temp_var = csv.DictReader(f)

# The file 'example_file.csv' is closed at this point

for i in temp_var:
    print(i)  # Produces a 'ValueError: I/O operation on closed file.'

temp_var 对象本质上是一个依赖于文件 f 的 CSV 读取器对象。当退出 with 块时,文件将被关闭,任何后续尝试读取该文件都将导致错误。

现在,当你这样做时:

with open('example_file.csv', 'r') as f:
    temp_var = csv.DictReader(f)

print(temp_var)  # Prints out a DictReader Object containing data from the CSV file

在这种情况下,您只是打印 temp_var 对象的表示形式,不需要从文件中读取。它本质上是向您显示有关对象本身的信息,而不是与其关联的文件的信息。但是,当您尝试在 with 块之外迭代 temp_var 时,它会尝试从关闭的文件中读取数据,从而导致“ValueError:对关闭的文件进行 I/O 操作。”

为了克服这个问题,您应该在 with 语句的范围内执行任何与文件相关的操作,例如迭代。如果您需要使用该范围之外的数据,可以将其存储在数据结构(例如列表)中,然后稍后对该结构进行操作:

import csv

data_list = []

with open('example_file.csv', 'r') as f:
    temp_var = csv.DictReader(f)
    data_list.extend(temp_var)

# Now you can work with data_list outside the with block
for i in data_list:
    print(i)

这样,您就可以在文件仍然打开的情况下将数据读取到 data_list 中,并且可以在 with 块之外对其执行操作,而不会遇到“ValueError:对已关闭文件进行 I/O 操作”。

© www.soinside.com 2019 - 2024. All rights reserved.