读取整个文件是否会留下文件句柄?

问题描述 投票:366回答:4

如果你用 content = open('Path/to/file', 'r').read() 在脚本退出之前,文件句柄是否一直处于打开状态? 有没有一种更简洁的方法来读取整个文件?

python file-io filehandle
4个回答
588
投票

这个问题的答案在一定程度上取决于特定的Python实现。

要了解这是怎么回事,请特别注意实际的 file 对象。 在你的代码中,这个对象只在一个表达式中被提到过一次,并且在表达式结束后立即变得不可访问。read() 调用返回。

这意味着文件对象是垃圾。 剩下的问题就是 "垃圾收集器什么时候会收集文件对象?"。

在使用引用计数器的CPython中,这种垃圾会立即被发现,所以会立即被收集。 其他python实现中一般不会出现这种情况。

为了确保文件被关闭,一个更好的解决方案是这种模式。

with open('Path/to/file', 'r') as content_file:
    content = content_file.read()

它总是会在块结束后立即关闭文件 即使发生了异常。

编辑:说得更细一点。

除了... file.__exit__(),它是 "自动 "调用的 with 上下文管理器设置,唯一的其他方式是 file.close() 自动调用(即除了自己明确调用外,)是通过 file.__del__(). 这让我们想到了一个问题,那就是什么时候 __del__() 被调用?

一个正确编写的程序不能假定最终程序会在程序终止前的任何时候运行。

-- https:/devblogs.microsoft.comoldnewthing20100809-00?p=13203。

特别是:

物体永远不会被显式销毁;但是,当它们无法到达时,它们可以被垃圾收集。实现可以推迟或完全省略垃圾收集。 - 如何实现垃圾收集是一个实施质量的问题,只要没有收集到仍然可以到达的对象。

[...]

CPython目前使用的是一种引用计算方案,带有(可选的)循环链接垃圾的延迟检测功能,一旦大部分对象无法到达,就会立即收集,但不能保证收集包含循环引用的垃圾。

-- https:/docs.python.org3.5referencedatamodel.html#objects-values-and-types。

(强调是我的)

但正如它所暗示的那样,其他实现可能会有其他行为。 举个例子,PyPy 6 不同的垃圾收集实现!


106
投票

你可以使用 pathlib.

对于Python 3.5及以上版本。

from pathlib import Path
contents = Path(file_path).read_text()

对于旧版本的Python,使用 pathlib2:

$ pip install pathlib2

那么

from pathlib2 import Path
contents = Path(file_path).read_text()

这就是实际情况 read_text 实施:

def read_text(self, encoding=None, errors=None):
    """
    Open the file in text mode, read it, and close the file.
    """
    with self.open(mode='r', encoding=encoding, errors=errors) as f:
        return f.read()

2
投票

好吧,如果你必须逐行读取文件以处理每一行,你可以使用

with open('Path/to/file', 'r') as f:
    s = f.readline()
    while s:
        # do whatever you want to
        s = f.readline()

或者更好的方法。

with open('Path/to/file') as f:
    for line in f:
        # do whatever you want to

0
投票

不把文件内容当作一个单一的字符串来检索,而是用一种很方便的方式 将内容存储为文件中所有行的列表:

with open('Path/to/file', 'r') as content_file:
    content_list = content_file.read().strip().split("\n")

可以看出,我们需要添加连接方法 .strip().split("\n")本主题的主要答案.

给你 .strip() 只是删除了整个文件字符串末尾的空格和换行符,而 .split("\n") 产生实际的列表,通过在每一个 换行字 \n.

此外,这种方式可以将整个文件的内容存储在一个变量中,在某些情况下,这可能是需要的,而不是像在这里指出的那样,逐行循环文件。此前的回答.

© www.soinside.com 2019 - 2024. All rights reserved.