zoukankan      html  css  js  c++  java
  • 【转】Python 3的pathlib模块:驯服文件系统

    【转】Python 3的pathlib模块:驯服文件系统

    https://python.freelycode.com/contribution/detail/1248

    Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。

    目录

    • python文件路径处理时的问题

    • 创建路径

    • 读写文件

    • 找出路径的组成部分

    • 移动和删除文件

    • 例子

      • 计算文件数量

      • 显示目录树

      • 查找上次修改的文件

      • 创建唯一的文件名

    • 操作系统的差别

    • 以合适的对象表现路径

    • 结论

    你是否遇到过使用python处理文件路径时的麻烦呢?在python 3.4以及更高版本中,这些麻烦不复存在。不再需要像下面这样从头开始编写代码:

    1.jpg

    或者编写下面这样冗长烦人的代码:

    2.jpg

    在这篇文章中,你将看到怎样使用python处理文件路径-目录和文件的名字。

    3.jpg

    python文件路径处理时的问题

    处理文件和与文件系统交互很重要,原因很多。 最简单的情况可能只涉及读取或写入文件,但有时会是更复杂的任务。也许您需要列出目录中属于给定类型的的所有文件,查找给定文件的父目录,或者创建一个不存在的唯一文件名。

    习惯上,Python使用常规文本字符串表示文件路径。 在os.path标准库的支持下,尽管有点麻烦,但这已经足够了(正如引言中的第二个例子所示)。然而,由于路径不是字符串,重要的功能遍布在标准库中,包括像os,glob和shutil这样的库。 下面的示例需要三个导入语句,以便将所有文本文件移动到归档目录:

    4.jpg

    对于由字符串表示的路径,使用常规字符串方法是可能的,但通常是一个坏主意。 例如,你应该使用os.path.join()来链接两条路径,它使用操作系统上正确的路径分隔符来链接路径,而不是像普通的字符串那样使用“+”。 回想一下Windows使用,而Mac和Linux使用/作为分隔符。 这种差异可能会导致难以发现的错误,例如我们介绍的第一个示例仅适用于Windows路径。

    Python 3.4中引入了pathlib模块(PEP 428)来处理这些挑战。 它在一个地方收集必要的功能,并通过易于使用的Path对象上的方法和属性使其可用。

    早期,其他软件包仍然使用字符串作为文件路径,但从Python 3.6开始,pathlib模块在整个标准库中得到支持,部分原因是由于增加了文件系统路径协议。 如果你坚持使用传统的Python,那么Python 2也有一个可用的向后移植。

    实践时间:让我们看看pathlib如何在实践中发挥作用。

    创建路径

    你真正需要知道的是pathlib.Path类。 创建路径有几种不同的方式。 首先,有类方法,如.cwd()(当前工作目录)和.home()(用户的主目录):

    5.jpg

    注意:在本教程中,我们将假定已经导入了pathlib,而没有像上面那样给出import pathlib。 由于您将主要使用Path类,因此您也可以使用语句from pathlib import Path并使用Path而不是pathlib.Path。

    还可以从其字符串表示中显式创建路径:

    6.jpg

    处理Windows路径的小技巧:在Windows上,路径分隔符是反斜杠。 但是,在许多情况下,反斜杠也用作转义字符以表示不可打印的字符。 为避免出现问题,请使用原始字符串来表示Windows路径。 这些字符串,它们前面都有一个r。 在原始字符串中,表示文字反斜线:r'C:Users'。

    构建路径的第三种方法是使用特殊运算符“/”链接路径的各个部分。 正斜杠操作符独立于平台上的实际路径分隔符使用:

    7.jpg

    只要至少有一个Path对象,/就可以连接多个路径或路径和字符串的混合(如上所述)。 如果你不喜欢特殊/符号,你可以用.joinpath()方法做同样的事情:

    8.jpg

    请注意,在前面的示例中,pathlib.Path由WindowsPath或PosixPath表示。 表示路径的实际对象取决于底层操作系统。 (也就是说,在Windows上结果表现为一个WindowsPath对象,而在Mac或Linux上结果表现为一个PosixPath对象。)有关更多信息,请参阅操作系统差异部分。

    读写文件

    习惯上,使用Python读取或写入文件的方法是使用内置的open()函数。 这仍然是正确的,因为open()函数可以直接使用Path对象。 以下示例查找Markdown文件中的所有标题并打印它们:

    9.jpg

    一个等同的选择是在Path对象上调用.open():

    10.jpg

    实际上,Path.open()在后台调用内置的open()。 你使用哪个选项主要是品味的问题。

    对于简单的文件读写,在pathlib库中有几个简便的方法:

    • .read_text(): 以文本模式打开路径并并以字符串形式返回内容。

    • .read_bytes(): 以二进制/字节模式打开路径并以字节串的形式返回内容。

    • .write_text(): 打开路径并向其写入字符串数据。

    • .write_bytes(): 以二进制/字节模式打开路径并向其写入数据。

    这些方法中的每一个都能处理文件的打开和关闭,使用起来非常简便,例如:

    11.jpg

    路径也可以指定为简单的文件名,在这种情况下,它们是相对于当前工作目录进行解析的。 以下示例等同于上一个示例:

    12.jpg

    .resolve()方法将找到完整路径。 下面,我们确认当前工作目录用于简单文件名:

    13.jpg

    请注意,比较路径时,比较的是它们的表示方式。 在上面的例子中,path.parent不等于pathlib.Path.cwd(),因为path.parent用'.'表示。 而pathlib.Path.cwd()由'/home/gahjelle/realpython/'表示。

    找出路径的组成部分

    路径的不同部分可以方便地用作属性。 基本的例子包括:

    • .name: 没有任何目录的文件名

    • .parent: 包含该文件的目录,或者如果path是目录,则是父目录

    • .stem: 文件名不带后缀

    • .suffix: 文件扩展名

    • .anchor: 目录之前的路径部分

    以下是这些属性的作用:

    14.jpg

    请注意.parent返回一个新的Path对象,而其他属性返回字符串。 这意味着,例如,可以像上一个示例那样链接.parent,甚至可以与/组合创建完全新的路径:

    15.jpg

    优秀的Pathlib备忘录提供了所有属性和方法的可视化表示。

    移动和删除文件

    通过pathlib,您还可以访问基本的文件系统级操作,如移动,更新甚至删除文件。 大多数情况下,这些方法不会在信息或文件丢失之前发出警告或等待确认。 使用这些方法时要小心。

    要移动文件,请使用.replace()。 请注意,如果目标已存在,.replace()将覆盖它。 不幸的是,pathlib没有明确支持安全移动文件。 为了避免可能覆盖目标路径,最简单的方法是在更换之前测试目标是否存在:

    16.jpg

    然而,这确实为可能的资源竞争留下隐患。 另一个进程可能会在执行if语句和.replace()方法之间的目标路径中添加一个文件。 如果这是一个问题,更安全的方法是打开独占创建的目标路径并明确复制源数据:

    17.jpg

    如果目标已经存在,上面的代码将引发FileExistsError。 从技术上讲,这复制了一个文件。 要执行移动,只需在完成复制后删除源(请参阅下文)。 确保没有发生异常。

    重命名文件时,有用的方法可能是.with_name()和.with_suffix()。 它们都返回原始路径,但分别替换名称或后缀。

    例如:

    18.jpg

    目录和文件可分别使用.rmdir()和.unlink()删除。 (再次提醒,要非常小心!)

    例子

    在本节中,您将看到一些如何使用pathlib来处理简单挑战的示例。

    计算文件数量

    列出大量文件有几种不同的方法。 最简单的是.iterdir()方法,它遍历给定目录中的所有文件。 以下示例将.iterdir()与collections.Counter类组合起来,以统计当前目录中每个文件类型的文件数量:

    19.jpg

    使用方法.glob()和.rglob()(递归glob)可以创建更灵活的文件列表。 例如,pathlib.Path.cwd()。glob('*.txt')返回当前目录中所有带有.txt后缀的文件。 以下仅计算以p开头的文件类型:

    20.jpg

    显示目录树

    下一个示例定义了一个函数tree(),它将打印一个表示文件层次结构的可视化树,该树以根目录为根。 在这里,我们也想列出子目录,所以我们使用.rglob()方法:

    21.jpg

    请注意,我们需要知道文件所在的目录到根目录有多远。 为此,我们首先使用.relative_to()来表示相对于根目录的路径。 然后,我们计算表示中的目录数量(使用.parts属性)。 运行时,此函数创建如下的可视化树:

    22.jpg

    • 注意:f-strings只能在Python 3.6及更高版本中使用。 在较老的Pythons中,表达式f'{spacer} + {path.name}'可以写为'{0} + {1}'.format(spacer,path.name)。

    查找上次修改的文件

    .iterdir(),.glob()和.rglob()方法非常适合生成器表达式和列表解析。 要在上次修改的目录中查找文件,可以使用.stat()方法获取有关底层文件的信息。 例如,.stat().st_mtime给出了文件上次修改的时间:

    23.jpg

    您甚至可以使用类似的表达式获取上次修改的文件的内容:

    24.jpg

    从不同的.stat().st_属性返回的时间戳表示1970年1月1日以来的秒数。除了datetime.fromtimestamp之外,time.localtime或time.ctime可用于将时间戳转换为更加可用的内容。

    创建一个唯一的文件名

    最后一个例子将显示如何基于模板构建唯一编号的文件名。 首先,为文件名指定一个模式,并为计数器留出空间。 然后,检查通过加入目录和文件名创建的文件路径是否存在(使用计数器的值)。 如果它已经存在,请增加计数器并重试:

    25.jpg

    如果该目录已经包含文件test001.txt和test002.txt,则上述代码将设置路径为test003.txt。

    操作系统差异

    早些时候,我们注意到当我们实例化pathlib.Path时,返回了WindowsPath或PosixPath对象。 对象的种类取决于您使用的操作系统。 该功能使编写跨平台兼容代码变得相当容易。 可以明确地询问WindowsPath或PosixPath,但您只会将代码限制在该系统中,没有任何好处。 这样的具体路径不能用于不同的系统:

    26.jpg

    有时可能需要表示路径而不访问底层文件系统(在这种情况下,在非Windows系统上表示Windows路径也是有意义的,反之亦然)。 这可以使用PurePath对象完成。 这些对象支持路径组件部分讨论的操作,但不支持访问文件系统的方法:

    27.jpg

    您可以直接在所有系统上实例化PureWindowsPath或PurePosixPath。 根据您使用的操作系统,实例化PurePath将返回其中一个对象。

    作为合适对象的路径

    在简介中,我们简单地指出路径不是字符串,pathlib背后的一个动机是用适当的对象表示文件系统。 事实上,pathlib的官方文档标题为pathlib--面向对象的文件系统路径。 在上面的例子中,面向对象的方法已经非常明显(特别是如果你将它与旧的os.path方式做对比)。 但是,让我给你留下一些其他小知识。

    与正在使用的操作系统无关,路径以Posix样式表示,正斜杠作为路径分隔符。 在Windows上,您将看到如下所示的内容:

    28.jpg

    但是,当路径转换为字符串时,它将使用本地形式,例如在Windows上使用反斜杠:

    29.jpg

    如果您正在使用不知道如何处理pathlib.Path对象的库,这特别有用。 这是3.6之前的Python版本中的一个大问题。 例如,在Python 3.5中,configparser标准库只能使用字符串路径来读取文件。 处理这种情况的方法是明确地转换为字符串:

    30.jpg

    在Python 3.6及更高版本中,如果需要进行显式转换,建议使用os.fspath()而不是str()。 这样会更安全一些,因为如果您偶然尝试转换不是路径的对象,它会引发错误。

    可能是pathlib库最不寻常的部分是使用/运算符。 窥探一下源码,让我们看看它是如何实现的。 这是运算符重载的一个例子:运算符的行为根据上下文而改变。 你以前见过这个。 想想+对于字符串和数字来说意味着不同的东西。 Python通过使用双下划线方法(a.k.a. dunder方法)来实现运算符重载。

    /运算符由.__ truediv __()方法定义。 事实上,如果你看看pathlib的源代码,你会看到类似于:

    31.jpg

    结论

    自Python 3.4以来,pathlib已经在标准库中可用。 使用pathlib,文件路径可以用适当的Path对象来表示,而不像以前那样用普通的字符串表示。 这些对象使代码处理文件路径:

    • 易于阅读,尤其是因为/用于将路径连接在一起

    • 功能更强大,可直接在对象上使用最必要的方法和属性

    • 在操作系统中更一致,因为不同系统的特性被Path对象隐藏

    英文原文:https://realpython.com/python-pathlib/
    译者:javylee
  • 相关阅读:
    scrapy中selenium的应用
    Django的锁和事务
    redis
    【leetcode】187. Repeated DNA Sequences
    【leetcode】688. Knight Probability in Chessboard
    【leetcode】576. Out of Boundary Paths
    【leetcode】947. Most Stones Removed with Same Row or Column
    【leetcode】948. Bag of Tokens
    【leetcode】946. Validate Stack Sequences
    【leetcode】945. Minimum Increment to Make Array Unique
  • 原文地址:https://www.cnblogs.com/langqi250/p/9759250.html
Copyright © 2011-2022 走看看