在Python中,OSError: [Errno 24] Too many open files错误很难调试。

9

我正在运行一段代码,有时候几小时后,有时候几分钟后就会出现以下错误:

OSError: [Errno 24] Too many open files

我在调试时遇到了一些麻烦。下面代码片段中的标记行总是触发错误。

try:
    with open(filename, 'rb') as f:
        contents = f.read()       <----- error triggered here
except OSError as e:
    print("e = ", e)
    raise
else:
    # other stuff happens

然而,我看不出这段代码有什么问题(对吧?),所以我猜测代码的其他部分没有正确地关闭文件。尽管我经常打开文件,但我总是使用“with”语句打开它们,我的理解是即使发生错误,文件也会被关闭(对吧?)。因此,我的代码的另一部分如下所示

    try:
        with tarfile.open(filename + '.tar') as tar:
            tar.extractall(path=target_folder)
    except tarfile.ReadError as e:
        print("e = ", e)
    except OSError as e:
        print("e = ", e)
    else:
        # If everything worked, we are done
        return

上面的代码经常遇到ReadError,但即使发生这种情况,文件也应该被关闭,对吧?那么我不明白为什么会遇到太多打开的文件?抱歉,这对您来说无法重现,因为我无法足够调试它,我只是在寻找一些提示,因为我迷失了。任何帮助都将不胜感激......

编辑:我使用 MacBook。以下是ulimit -a的输出:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 256
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1418
virtual memory          (kbytes, -v) unlimited

根据 @sj95126 的建议,我更改了有关 tar 文件的代码,确保文件已关闭。

try:
    tar = tarfile.open(filename + '.tar')
    tar.extractall(path=target_folder)
except tarfile.ReadError as e:
    print("tarfile.ReadError e = ", e)
except OSError as e:
    print("e = ", e)
else:
    # If everything worked, we are done
    return
finally:
    print("close tar file")
    try:
        tar.close()
    except:
        print("file already closed")

但这并没有解决问题。


如果您正在使用Linux,请在终端中使用“ulimit -a”命令告诉我“文件锁”的值。 - alexzander
1
通常情况下,您是正确的,with应该导致文件被关闭;但是,管理对象中总是存在错误的可能性。tarfile对象必须关闭文件,with无法到达file对象并执行此操作。仅供测试,请尝试在try中添加finally子句,并显式调用tar.close(),看看是否有所帮助。 - sj95126
感谢大家的评论。@alexzander我在上面添加了ulimit -a。 - carl
@sj95126 这是一个非常好的观点。我会测试你的建议。 - carl
@Carcigenicate,我在处理文件时有很多类似的情况,但它们都具有相同的语法,并且是按顺序使用而不是并行使用。我非常确定这一定是我的代码问题,因为即使我停止了所有其他程序,我仍然会遇到这个错误。 - carl
显示剩余2条评论
1个回答

0
在Unix/Linux系统中,您可以使用命令ulimit -a检查文件锁定或打开文件限制的总数。在@carl的情况下,输出如下:
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 256
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1418
virtual memory          (kbytes, -v) unlimited

正如您所看到的,打开文件文件锁等于256

open files                      (-n) 256

这是一个非常的值

@carl的存档至少包含256个文件;因此,Python使用文件处理程序打开每个文件,这将导致系统文件锁定(为了在系统上打开文件,您需要文件锁定,就像指向该文件的指针一样;要访问数据,请随意操作)

解决方案是将打开文件的值设置为无限制非常大的数字。

根据stack answer,以下是如何更改限制的方法


4
但我总是关闭文件,并且一次只打开一个文件。所以我不太明白为什么会遇到这个问题。我的代码中肯定有一些没有正确关闭文件的地方,我宁愿找出这个错误,而不是将限制设置为更大的数字。 - carl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接