【问题标题】:Recommended way of closing files using pathlib module?使用 pathlib 模块关闭文件的推荐方法?
【发布时间】:2026-01-24 23:45:01
【问题描述】:

从历史上看,我一直使用以下方法来读取python 中的文件:

with open("file", "r") as f:
    for line in f:
        # do thing to line

这仍然是推荐的方法吗?使用以下内容是否有任何缺点:

from pathlib import Path

path = Path("file")
for line in path.open():
    # do thing to line

我发现的大多数参考资料都使用with 关键字来打开文件,以便不必显式关闭文件。这适用于这里的迭代器方法吗?

with open() docs

【问题讨论】:

  • 嗯,是的。在第二个示例中,您仍然缺少文件关闭部分。不知道为什么会有Path 的差异——with path.open() as f: 与第一个示例相同,而for line in open("file", "r"): 与第二个示例相同。
  • 你应该在第二个例子中显式调用path.close()
  • Path.open() 文档本身使用了一个仍然使用 with 的示例。
  • 3 - 0 - 我将继续使用 with ... @GinoMempin - 完全错过了文档中的内容,谢谢。 @RishiDev - 没有 path.close() 方法,因为 path.open 正在返回一个文件对象 @Ry- - 当文件在循环结束时被清除时,文件是否未被 python 关闭?没有任何变量可以调用close() on?
  • 语言不保证。 CPython 的引用计数在循环后立即关闭文件,但最好与其他 Python 实现互操作,并继续使用 with 进行可预测的确定性关闭。 (另外,如果在循环中抛出异常,我不知道引用是否会在 CPython 上徘徊一段时间。)

标签: python python-3.x with-statement pathlib


【解决方案1】:

尚未提及的事情:如果您只想读取或写入一些文本(或字节),那么您在使用 pathlib 时不再需要显式使用上下文管理器:

>>> import pathlib
>>> path = pathlib.Path("/tmp/example.txt")
>>> path.write_text("hello world")
11
>>> path.read_text()
'hello world'
>>> path.read_bytes()
b'hello world'

打开文件以迭代行仍应使用 with 语句,原因与使用带有 open 的上下文管理器相同的原因,如 the docs show

>>> with path.open() as f:
...     for line in f:
...         print(line)
...
hello world

【讨论】:

  • 好点,这些函数的代码已经在幕后使用with self.open :-)
【解决方案2】:

请记住,Path 对象用于处理文件系统路径。就像 Python 的 built-in library 一样,有一个 open 方法,但在 Path 对象中没有关闭。

.close 位于由内置 open 或使用 Path 对象的 open 方法返回的文件句柄中:

>>> from pathlib import Path
>>> p=Path(some_file)
>>> p
PosixPath('/tmp/file')

您可以使用内置的 open 函数或 Path 对象中的 open 方法打开该 Path 对象:

>>> fh=open(p)    # open built-in function
>>> fh
<_io.TextIOWrapper name='/tmp/file' mode='r' encoding='UTF-8'>
>>> fh.close()

>>> fh=p.open()   # Path open method which aliases to os.open
>>> fh
<_io.TextIOWrapper name='/tmp/file' mode='r' encoding='UTF-8'>
>>> fh.close()

您可以查看pathlib on Github 的源代码,了解pathlib 的作者如何在他们自己的代码中执行此操作。

我观察到的是三件事之一。

目前最常见的是使用with

from pathlib import Path 

p=Path('/tmp/file')

#create a file
with p.open(mode='w') as fi:
    fi.write(f'Insides of: {str(p)}')

# read it back and test open or closed
with p.open(mode='r') as fi:
    print(f'{fi.read()} closed?:{fi.closed}')

# prints 'Insides of: /tmp/file closed?:False'

您可能知道,在 with 块的末尾会调用 __exit__ 方法。对于文件,这意味着文件已关闭。这是pathlib源代码中最常用的方法。

其次,您还可以在源代码中看到 pathlib 对象维护进入和退出状态以及打开和关闭文件的标志。但是,os.close 函数没有被显式调用。您可以使用 .closed 访问器检查该状态。

fh=p.open()
print(f'{fh.read()} closed?:{fh.closed}')
# prints Insides of: /tmp/file closed?:False    
# fi will only be closed when fi goes out of scope...
# or you could (and should) do fh.close()


with p.open() as fi:
    pass
print(f'closed?:{fi.closed}')   
# fi still in scope but implicitly closed at the end of the with bloc
# prints closed?:True

第三,在 cPython 上,当文件句柄超出范围时,文件将被关闭。这不是可移植的或被认为是不可依赖的“良好实践”,但通常是这样。 pathlib 源代码中有这样的实例。

【讨论】:

  • 'sup @dawg - 谢谢,这是一个非常全面的答案。我想我在pathlib 中引用了一些红鲱鱼,但答案似乎是我将依赖实现细节而不是语言特性。
【解决方案3】:

Pathlib 是用于操作文件系统路径的面向对象的方式。

使用 pathlib 模块打开文件的推荐方法是使用上下文管理器:

p = Path("my_file.txt")

with p.open() as f:
    f.readline()

这样可以确保在使用后关闭文件。


在您提供的两个示例中,您并没有关闭文件,因为您就地打开它们。

由于p.open() 返回文件对象,您可以通过分配它并检查属性closed 来测试它,如下所示:

from pathlib import Path

path = Path("file.txt")

# Open the file pointed by this path and return a file object, as
# the built-in open() function does.
f = path.open()
for line in f:
    # do some stuff

print(f.closed)  # Evaluates to False.

【讨论】: