ValueError: I/O operation on closed file within context manager scope
ValueError: I/O operation on closed file within context manager scope
我读过很多类似的问题,但其中大部分都是通过修复缩进来解决的,所以要么我一无所知,要么有一些简单的方法可以解决我的问题,但我认为这与标识无关。
所以我有这个函数,它基本上使用两个 *.txt 文件和 returns namedtuples
的生成器对象执行几个操作,其中包含一些我需要稍后查找的信息。
def master_reader(file1, file2):
with open(file1, "r", encoding="utf-8") as genomas:
with open(file2, "r", encoding="utf-8") as listas:
l = parser_listas(listas)
f = parser_genomas(genomas)
f = map(intifier, f)
f = (people_maker(linea, l) for linea in f)
f = map(genotipo_getter, f)
f = map(fen_getter, f)
return f
当我调用它并将其分配给 variable.But 时一切正常它:
print(valor_caracteristica("TCT", "Luna Lovegood", master_reader("genomas.txt", "listas.txt")))
但是我遇到了这个异常:
Original exception was:
Traceback (most recent call last):
File "lib.py", line 204, in <module>
print(valor_caracteristica("TCT", "Luna Lovegood", master_reader("genomas.txt", "listas.txt")))
File "lib.py", line 194, in valor_caracteristica
a = next(filter(lambda x: x.nombre == nombre, file))
File "lib.py", line 185, in <genexpr>
f = (people_maker(linea, l) for linea in f)
ValueError: I/O operation on closed file.
map()
returns 一个迭代器。只有当你遍历一个 map()
对象时,它才会真正将该函数应用于输入可迭代对象的下一个元素。
因此,在您开始使用 map
对象和底层生成器表达式之前,没有从您的文件中读取任何数据。您在函数之外执行此操作,此时文件已经关闭,因为 return f
语句退出了函数并扩展了上下文。
解决方法是不使用像 map()
这样的惰性对象,或者使您的函数成为 生成器函数 。后者不会退出(并向 with
块发出信号以退出上下文),直到您完成文件。
这可以通过使用 yield from
:
非常简单地完成
def master_reader(file1, file2):
with open(file1, "r", encoding="utf-8") as genomas:
with open(file2, "r", encoding="utf-8") as listas:
l = parser_listas(listas)
f = parser_genomas(genomas)
f = map(intifier, f)
f = (people_maker(linea, l) for linea in f)
f = map(genotipo_getter, f)
yield from map(fen_getter, f)
yield from
保持生成器打开直到底层 map()
对象引发 StopIteration
.
一个说明差异的快速演示:
>>> from contextlib import contextmanager
>>> @contextmanager
... def democtx():
... print('Entering the context')
... yield
... print('Exiting the context')
...
>>> def return_map():
... with democtx():
... return map(lambda x: x**2, range(3))
...
>>> def yield_from_map():
... with democtx():
... yield from map(lambda x: x**2, range(3))
...
>>> example1 = return_map()
Entering the context
Exiting the context
>>> example2 = yield_from_map()
>>> next(example2)
Entering the context
0
>>> next(example2)
1
>>> next(example2)
4
>>> next(example2)
Exiting the context
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
注意 example1
上下文如何在 return 后立即退出,而 example2
直到迭代开始才打开上下文,并且直到我们迭代进入才关闭上下文填满 map()
对象。
由于您使用的是 Python 3
,map
构造了 returns 生成器,这些生成器是延迟计算的。因此,当生成器 f
被评估时,文件处理程序已经关闭(打开文件的上下文管理器确保了这一点)。
解决方案是评估其中的地图,或者根本不使用它们,并使用列表理解。
return list(f) # evaluate the map statement therein.
# or you should just return a generator as @MartinPieters suggested.
我读过很多类似的问题,但其中大部分都是通过修复缩进来解决的,所以要么我一无所知,要么有一些简单的方法可以解决我的问题,但我认为这与标识无关。
所以我有这个函数,它基本上使用两个 *.txt 文件和 returns namedtuples
的生成器对象执行几个操作,其中包含一些我需要稍后查找的信息。
def master_reader(file1, file2):
with open(file1, "r", encoding="utf-8") as genomas:
with open(file2, "r", encoding="utf-8") as listas:
l = parser_listas(listas)
f = parser_genomas(genomas)
f = map(intifier, f)
f = (people_maker(linea, l) for linea in f)
f = map(genotipo_getter, f)
f = map(fen_getter, f)
return f
当我调用它并将其分配给 variable.But 时一切正常它:
print(valor_caracteristica("TCT", "Luna Lovegood", master_reader("genomas.txt", "listas.txt")))
但是我遇到了这个异常:
Original exception was:
Traceback (most recent call last):
File "lib.py", line 204, in <module>
print(valor_caracteristica("TCT", "Luna Lovegood", master_reader("genomas.txt", "listas.txt")))
File "lib.py", line 194, in valor_caracteristica
a = next(filter(lambda x: x.nombre == nombre, file))
File "lib.py", line 185, in <genexpr>
f = (people_maker(linea, l) for linea in f)
ValueError: I/O operation on closed file.
map()
returns 一个迭代器。只有当你遍历一个 map()
对象时,它才会真正将该函数应用于输入可迭代对象的下一个元素。
因此,在您开始使用 map
对象和底层生成器表达式之前,没有从您的文件中读取任何数据。您在函数之外执行此操作,此时文件已经关闭,因为 return f
语句退出了函数并扩展了上下文。
解决方法是不使用像 map()
这样的惰性对象,或者使您的函数成为 生成器函数 。后者不会退出(并向 with
块发出信号以退出上下文),直到您完成文件。
这可以通过使用 yield from
:
def master_reader(file1, file2):
with open(file1, "r", encoding="utf-8") as genomas:
with open(file2, "r", encoding="utf-8") as listas:
l = parser_listas(listas)
f = parser_genomas(genomas)
f = map(intifier, f)
f = (people_maker(linea, l) for linea in f)
f = map(genotipo_getter, f)
yield from map(fen_getter, f)
yield from
保持生成器打开直到底层 map()
对象引发 StopIteration
.
一个说明差异的快速演示:
>>> from contextlib import contextmanager
>>> @contextmanager
... def democtx():
... print('Entering the context')
... yield
... print('Exiting the context')
...
>>> def return_map():
... with democtx():
... return map(lambda x: x**2, range(3))
...
>>> def yield_from_map():
... with democtx():
... yield from map(lambda x: x**2, range(3))
...
>>> example1 = return_map()
Entering the context
Exiting the context
>>> example2 = yield_from_map()
>>> next(example2)
Entering the context
0
>>> next(example2)
1
>>> next(example2)
4
>>> next(example2)
Exiting the context
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
注意 example1
上下文如何在 return 后立即退出,而 example2
直到迭代开始才打开上下文,并且直到我们迭代进入才关闭上下文填满 map()
对象。
由于您使用的是 Python 3
,map
构造了 returns 生成器,这些生成器是延迟计算的。因此,当生成器 f
被评估时,文件处理程序已经关闭(打开文件的上下文管理器确保了这一点)。
解决方案是评估其中的地图,或者根本不使用它们,并使用列表理解。
return list(f) # evaluate the map statement therein.
# or you should just return a generator as @MartinPieters suggested.