在try-except块中使用open,打开的文件过多?
简单来说,我正在一个特定的位置遍历所有的子文件夹,并从三个不同的文件中收集一些数字。
def GrepData():
import glob as glob
import os as os
os.chdir('RUNS')
RUNSDir = os.getcwd()
Directories = glob.glob('*.*')
ObjVal = []
ParVal = []
AADVal = []
for dir in Directories:
os.chdir(dir)
(X,Y) = dir.split(sep='+')
AADPath = glob.glob('Aad.out')
ObjPath = glob.glob('fobj.out')
ParPath = glob.glob('Par.out')
try:
with open(os.path.join(os.getcwd(),ObjPath[0])) as ObjFile:
for line in ObjFile:
ObjVal.append(list([X,Y,line.split()[0]]))
ObjFile.close()
except(IndexError):
ObjFile.close()
try:
with open(os.path.join(os.getcwd(),ParPath[0])) as ParFile:
for line in ParFile:
ParVal.append(list([X,Y,line.split()[0]]))
ParFile.close()
except(IndexError):
ParFile.close()
try:
with open(os.path.join(os.getcwd(),AADPath[0])) as AADFile:
for line in AADFile:
AADVal.append(list([X,Y,line.split()[0]]))
AADFile.close()
except(IndexError):
AADFile.close()
os.chdir(RUNSDir)
每次打开文件的命令都放在一个尝试 - 捕获的代码块里,因为有时候打开的文件可能是空的,这样在尝试使用line.split()时就会出现索引错误,因为列表是空的。
但是当我运行这个脚本时,我遇到了以下错误:“OSError: [Errno 24] 打开的文件太多了”。
我原以为“with open...”这个写法是可以在使用完文件后自动关闭它?显然这并没有发生。
所以我想问两件事:
- 我的理解“with open”是正确的吗?
- 我该如何修正导致这个问题的错误?
(是的,我知道代码看起来不太优雅。整个尝试 - 捕获的部分应该是一个可以重复使用的对象 - 但我会在弄清楚这个错误后再去修正它)
2 个回答
"打开的文件太多"这个问题和你写的Python代码是否语法正确没有关系,你使用with
的方式也是对的。关键在于错误信息中的"OSError",这指的是底层的操作系统。
当你调用open()时,Python解释器会执行一个系统调用。这个系统调用的具体细节会根据你使用的操作系统有所不同,但在Linux上,这个调用是open(2)。操作系统的内核会处理这个系统调用。在文件打开的期间,它会在系统文件表中占有一个条目,并占用操作系统的资源——这意味着文件在打开时实际上是“占用空间”的。因此,操作系统对同时可以打开的文件数量是有限制的。
你的问题在于,当你调用open()时,没有足够快地调用close()。如果你的目录结构需要同时打开成千上万的文件,这可能会接近这个限制,这个限制在Linux上是可以临时调整的(不过我对其他操作系统不太熟悉,所以不想深入讨论跨平台的具体做法)。
试着把你的 try-except
放到 with
里面,像这样:
with open(os.path.join(os.getcwd(),ObjPath[0])) as ObjFile:
for line in ObjFile:
try:
ObjVal.append(list([X,Y,line.split()[0]]))
except(IndexError):
pass
注意:你不需要手动关闭文件,这就是 with
的作用。另外,如果你使用的是相同的名字,就不需要在导入时使用 as os
。