python mmap.error:打开的文件过多,怎么回事?

6 投票
4 回答
4004 浏览
提问于 2025-04-16 16:39

我正在使用 pupynere 接口(在 Linux 系统上)读取一堆 netcdf 文件。下面的代码出现了 mmap 错误:

import numpy as np
import os, glob
from pupynere import NetCDFFile as nc
alts = []
vals = []
path='coll_mip'
filter='*.nc'
for infile in glob.glob(os.path.join(path, filter)):
        curData = nc(infile,'r')
        vals.append(curData.variables['O3.MIXING.RATIO'][:])
        alts.append(curData.variables['ALTITUDE'][:])
        curData.close()

错误信息:

$ python2.7 /mnt/grid/src/profile/contra.py
Traceback (most recent call last):
  File "/mnt/grid/src/profile/contra.py", line 15, in <module>
  File "/usr/lib/python2.7/site-packages/pupynere-1.0.13-py2.7.egg/pupynere.py", line 159, in __init__
  File "/usr/lib/python2.7/site-packages/pupynere-1.0.13-py2.7.egg/pupynere.py", line 386, in _read
  File "/usr/lib/python2.7/site-packages/pupynere-1.0.13-py2.7.egg/pupynere.py", line 446, in _read_var_array
mmap.error: [Errno 24] Too many open files

有趣的是,如果我注释掉其中一个 append 命令(任意一个都可以!),代码就能正常运行!我到底哪里出错了?我不是已经关闭文件了吗?这似乎和 Python 的列表有关。我之前用过一种不同但效率低的方法 (总是复制每个元素),那种方法是可以的。

顺便说一下:ulimit -n 的结果是 1024,程序在处理到第 498 个文件时失败。

这可能和这个有关,但解决方案对我没用: NumPy 和 memmap: [Errno 24] 打开的文件太多

4 个回答

2

嗯……也许,可能,with curData可以解决这个问题?这只是一个大胆的猜测。


编辑:请问curData有没有一个叫Flush的方法?你试过在Close之前调用它吗?


编辑 2: Python 2.5的with语句(直接来自于理解Python的“with”语句

with open("x.txt") as f:
    data = f.read()
    do something with data

……基本上它总是会关闭资源(就像C#的using结构一样)。

3

@corlettk: 是的,因为这是Linux系统,所以可以使用 strace -e trace=file 命令。

strace -e trace=file,desc,munmap python2.7 /mnt/grid/src/profile/contra.py

这个命令会显示出具体在什么时间打开了哪些文件,甚至还会显示文件描述符。

你也可以使用

ulimit -a

来查看当前有哪些限制在生效。

编辑

gdb --args python2.7 /mnt/grid/src/profile/contra.py
(gdb) break dup
(gdb) run

如果这样会导致在与映射文件相关的断点之前出现太多的断点,你可能想先不设置断点运行一段时间,然后手动中断(按Ctrl+C),再在“正常”运行时设置断点;也就是说,如果你有足够的时间的话 :)

一旦中断,就可以用

(gdb) bt
7

我猜测在pupynere中的mmap.mmap调用可能会保持文件描述符处于打开状态(或者是创建了一个新的文件描述符)。你可以试试这样做:

vals.append(curData.variables['O3.MIXING.RATIO'][:].copy())
alts.append(curData.variables['ALTITUDE'][:].copy())

撰写回答