关闭ipython中所有打开的文件
有时候在使用ipython的时候,你可能会遇到一个问题,这个问题发生在一个打开了文件进行写入的函数里。这意味着下次你再运行这个函数时,会出现一个值错误,
值错误:文件 'filename' 已经打开。请在重新以写入模式打开之前先关闭它。
但是,由于这个函数出错了,文件的句柄(也就是在函数内部创建的那个)就丢失了,所以无法关闭。解决这个问题的唯一办法似乎就是关闭ipython会话,这时你会看到这样的提示:
正在关闭剩余的打开文件:filename... 完成
有没有办法让ipython在不退出会话的情况下关闭这些文件呢?
2 个回答
这里有几个建议:
- 在处理文件时,最好总是使用
finally
(或者with
语句),这样可以确保文件被正确关闭。 - 你可以直接关闭一些非标准的文件描述符,方法是使用
os.close(n)
,其中n
是大于2的数字(这适用于Unix系统,所以你可以查看/proc/ipython_pid/fd/
来看看当前进程打开了哪些描述符)。 - 你可以检查捕获的堆栈帧中的局部变量,看看能否找到那个出问题的文件的引用并将其关闭……可以查看
sys.last_traceback
。
在处理文件时,建议你总是使用 with
语句。比如,你可以这样写:
with open("x.txt") as fh:
...do something with the file handle fh
这样做的好处是,如果在 with
代码块执行过程中出现了问题,比如发生了错误,文件会被自动关闭。想了解更多,可以查看关于 with 的文档。
补充说明:根据评论中的讨论,提问者似乎需要同时打开多个文件,并且需要同时使用多个文件中的数据。显然,给每个打开的文件都写一个嵌套的 with
语句并不是个好主意,这样会让代码变得复杂,而我们通常希望代码保持简单。
一个可行的办法是把计算过程放在一个 try
/finally
代码块中。比如:
file_handles = []
try:
for file in file_list:
file_handles.append(open(file))
# Do some calculations with open files
finally:
for fh in file_handles:
fh.close()
在 finally
代码块中包含的代码会在任何 try
、except
或 else
代码块执行完后运行,即使发生了错误也会执行。从文档中可以了解到:
如果有
finally
,它会指定一个“清理”处理程序。try
代码块会被执行,包括任何except
和else
代码块。如果在这些代码块中发生了错误且没有被处理,这个错误会被暂时保存。接着会执行finally
代码块。如果有保存的错误,它会在finally
代码块结束时被重新抛出。如果finally
代码块抛出了另一个错误,或者执行了返回或跳出语句,那么之前保存的错误就会丢失。在执行finally
代码块时,程序无法访问错误信息。