为什么Python有文件句柄数量限制?

30

我写了一个简单的测试代码,想知道在Python脚本中可以打开多少个文件:

for i in xrange(2000):
    fp = open('files/file_%d' % i, 'w')
    fp.write(str(i))
    fp.close()

fps = []
for x in xrange(2000):
    h = open('files/file_%d' % x, 'r')
    print h.read()
    fps.append(h)

然后我得到了一个异常

IOError: [Errno 24] Too many open files: 'files/file_509'

在 Fedora 14 和 Python 2.7 上,我在 1021 上遇到了此错误。 - Ruggero Turra
6
@wiso,+stdin、stdout和stderr加起来等于1024——我在哪里见过这个数字? - John La Rooy
1
你应该使用 try..finallywith 来安全地关闭文件。至于你的问题:也许你想告诉我们你要做什么,因为你的代码对我来说毫无意义。 - schlamar
@gnibber:ulimit -n 告诉我是1024。我认为你还需要将 /usr/lib64/python2.7/atexit.py/home/xyz/.pystartup 也算作已打开的文件。 - Ruggero Turra
如果您在同一操作系统上尝试使用其他编程语言,您很快就会发现这不是Python的限制。 - johnsyweb
7个回答

41

操作系统会限制打开文件的数量。在Linux下,您可以输入以下命令:

ulimit -n

想要查看限制是多少。如果你是root用户,可以输入

ulimit -n 2048

现在你的程序可以正常运行(作为根用户),因为你已经将打开文件限制提高到2048个


14
如果您想使用 Python 代码检查限制,请使用 import resource; print resource.getrlimit(resource.RLIMIT_NOFILE) - mouad
2
显然,您不需要成为root用户就可以更改它(我刚试过!) - chuse

15

当我运行你的代码时,我在Windows上看到了相同的行为。这个限制是由C运行时存在的。你可以使用win32file来更改限制值:

import win32file

print win32file._getmaxstdio()

以上应该给你512,这解释了在#509处失败的原因(如其他人已经说明的那样,包括标准输入,标准错误和标准输出)

执行以下命令,你的代码就可以正常运行:

win32file._setmaxstdio(2048)

需要注意2048是硬限制,也就是C Stdio底层的硬限制。因此,对我来说,当使用一个大于2048的值来执行_setmaxstdio时,会失败。


3
为了使这个工作正常运行,我首先需要进行以下安装:pip install pywin32 - B K
1
请注意,从2022年开始,C运行时库现在支持8192个打开文件的上限,而不是2048。请参阅Microsoft关于_setmaxstdio函数的文档 - Nick Muise

10

要检查Linux上打开的文件句柄限制,您可以使用Python模块resource

import resource

# the soft limit imposed by the current configuration
# the hard limit imposed by the operating system.
soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE)
print 'Soft limit is ', soft 

# For the following line to run, you need to execute the Python script as root.
resource.setrlimit(resource.RLIMIT_NOFILE, (3000, hard))

在Windows上,我按照Punit S的建议进行操作:
import platform

if platform.system() == 'Windows':
    import win32file
    win32file._setmaxstdio(2048)

我注意到在Ubuntu中运行setrlimit时不必使用root权限。 - 林果皞

7

很可能是因为操作系统对应用程序可以打开的文件数量有限制。


2
在Windows上,可以使用内置的ctypes库获取或设置限制:
import ctypes
print("Before: {}".format(ctypes.windll.msvcrt._getmaxstdio()))
ctypes.windll.msvcrt._setmaxstdio(2048)
print("After: {}".format(ctypes.windll.msvcrt._getmaxstdio()))

0

由于这不是一个Python问题,所以请执行以下操作:

for x in xrange(2000):
    with open('files/file_%d' % x, 'r') as h:
        print h.read()

以下是一个非常糟糕的想法。

fps.append(h)

1
这个想法是好是坏取决于你在做什么。即使是Guido本人也使用这种保持打开文件的策略来进行特定排序算法:http://neopythonic.blogspot.com/2008/10/sorting-million-32-bit-integers-in-2mb.html - EML
1
@S.Lott:您能解释一下为什么您认为 fps.append(h) 是一个不好的主意吗?(您会建议哪种替代方案?) - iCanLearn

-1

需要使用append,这样垃圾回收器就不会清理和关闭文件。


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