Pythonpathlib教程展示了如何在Python中使用pathlib模块处理文件和目录。
pathlib
是一个Python模块,它提供了一个用于处理文件和目录的对象API。pathlib
是一个标准模块。
Path
是处理文件的核心对象。
$ pip install prettytable $ pip install more_itertools
在本教程中,我们还将使用prettytable
和more_itertools
。
blue forest sky ocean rabbit clue
一些示例使用这个简单的文本文件。
路径cwd和home
我们使用cwd
获取当前工作目录,使用home
获取主目录。
#!/usr/bin/python from pathlib import Path print(f"Current directory: {Path.cwd()}") print(f"Home directory: {Path.home()}")
该示例打印当前工作目录和主目录。
$ cwd_home.py Current directory: C:\Users\Jano\Documents\pyprogs\pathlib Home directory: C:\Users\Jano
Pythonpathlib当前文件
__file__
给出了当前运行程序的路径。
#!/usr/bin/python from pathlib import Path p = Path(__file__) print(p)
该示例打印程序的路径。
$ ./current.py /home/jano/Documents/prog/python/tmp/current.py
Pythonpathlib改变目录
我们使用os'
chdir
进入另一个目录。
#!/usr/bin/python from pathlib import Path from os import chdir path = Path('..') print(f'Current working directory: {path.cwd()}') chdir(path) print(f'Current working directory: {path.cwd()}') chdir('..')
我们更改当前工作目录。请注意,该目录仅在Python程序内部更改。
$ change_dir.py Current working directory: C:\Users\Jano\Documents\pyprogs\pathlib Current working directory: C:\Users\Jano\Documents\pyprogs
路径mkdir
使用mkdir
创建一个新目录。
#!/usr/bin/python from pathlib import Path path = Path.cwd() / 'new' path.mkdir()
该示例在当前工作目录中创建一个新目录。
Pythonpathlib复制文件
借助shutil
模块,我们复制了一个文件。
#!/usr/bin/python from pathlib import Path from shutil import copyfile source = Path('words.txt') destination = Path('words_bck.txt') copyfile(source, destination)
该示例复制了一个words.txt
文件。
source = Path('words.txt')
通过将文件名传递给Path
构造函数来创建文件对象。
连接路径
路径可以用/
运算符或joinpath
方法连接。
#!/usr/bin/python from pathlib import Path path = Path.home() docs = path / 'Documents' pictures = path / 'Pictures' print(docs) print(pictures)
在示例中,我们使用/
连接两条路径。
$ join_path.py C:\Users\Jano\Documents C:\Users\Jano\Pictures
路径触摸
touch
创建一个新的空文件;它等同于Linuxtouch命令。
#!/usr/bin/python from pathlib import Path Path('myfile.txt').touch()
我们创建一个新的空myfile.txt
。
路径重命名
rename
重命名文件或目录。
#!/usr/bin/python from pathlib import Path path = Path('names.txt') path.rename('mynames.txt')
该示例将当前工作目录中的names.txt
重命名为mynames.txt
。
路径名
我们用文件的绝对路径或相对路径来引用文件。路径有不同的表示;Windows使用与Linux不同的文件路径。
#!/usr/bin/python from pathlib import Path path = Path('C:/Users/Jano/Downloads/wordpress-5.1.tar.gz') print(path) print(path.as_uri()) print(path.as_posix())
该示例显示了三种不同的文件路径结构。
$ path_names.py C:\Users\Jano\Downloads\wordpress-5.1.tar.gz file:///C:/Users/Jano/Downloads/wordpress-5.1.tar.gz C:/Users/Jano/Downloads/wordpress-5.1.tar.gz
第一个是Windows文件路径。第二个是URI样式。第三种是POSIX风格。
相对路径
相对路径从某个给定的工作目录开始,无需提供完整的绝对路径。例如,data.txt
是从/home/users/jano的角度到
/home/users/jano/data.txt
的相对路径/目录。
换句话说,当我们位于/home/users/jano/
目录时,我们可以简单地通过文件名data.txt
关联到该文件,无需指定完整路径。
#!/usr/bin/python from pathlib import Path path = Path('C:/Users/Jano/Downloads/wordpress-5.1.tar.gz') home = Path.home() relative = path.relative_to(home) print(relative)
该示例打印给定主目录的归档文件的相对路径。
$ relative_path.py Downloads\wordpress-5.1.tar.gz
路径父母
通过parent
和parents
,我们可以获得路径的逻辑父级。
#!/usr/bin/python from pathlib import Path path = Path('C:/Users/Jano/Documents') print(f"The parent directory of {path} is {path.parent}") print(f"The parent of the parent of {path} is {path.parent.parent}") print(f"All the parents of {path.parent}: ") print(list(path.parents))
该示例打印路径的父级。
print(f"The parent of the parent of {path} is {path.parent.parent}")
我们可以获得父对象的父对象。
$ parents.py The parent directory of C:\Users\Jano\Documents is C:\Users\Jano The parent of the parent of C:\Users\Jano\Documents is C:\Users All the parents of C:\Users\Jano: [WindowsPath('C:/Users/Jano'), WindowsPath('C:/Users'), WindowsPath('C:/')]
路径部分
路径由子元素组成,例如drive或root。
#!/usr/bin/python from pathlib import Path path = Path('C:/Users/Jano/Documents') print(path.parts) print(path.drive) print(path.root)
程序打印路径的某些部分。
print(path.parts)
部分
可以访问路径的各种组件。
print(path.drive)
drive
给出一个表示驱动器字母或名称的字符串,如果有的话。
print(path.root)
root
给出一个表示(本地或全局)根的字符串,如果有的话。
$ parts.py ('C:\\', 'Users', 'Jano', 'Documents') C: \
下面的程序给出了路径的其他部分。
#!/usr/bin/python from pathlib import Path import os path = Path('C:/Users/Jano/Downloads/wordpress-5.1.tar.gz') print(f"The stem is: {path.stem}") print(f"The name is: {path.name}") print(f"The suffix is: {path.suffix}") print(f"The anchor is: {path.anchor}") print(f"File name: {os.path.splitext(path.stem)[0]}") print("The suffixes: ") print(path.suffixes)
程序打印词干、名称、后缀和锚点。
$ parts2.py The stem is: wordpress-5.1.tar The name is: wordpress-5.1.tar.gz The suffix is: .gz The anchor is: C:\ File name: wordpress-5.1 The suffixes: ['.1', '.tar', '.gz']
路径列表目录
iterdir
生成目录内容的路径对象。
#!/usr/bin/python from pathlib import Path path = Path('C:/Users/Jano/Documents') dirs = [e for e in path.iterdir() if e.is_dir()] print(dirs)
该示例打印指定目录的子目录。我们检查路径对象是否是带有is_dir
的目录。
以下示例打印指定目录中的文件。
#!/usr/bin/python from pathlib import Path path = Path('C:/Users/Jano/Documents') files = [e for e in path.iterdir() if e.is_file()] print(files)
我们检查路径对象是否为带有is_file
的文件。
路径通配符
全局模式指定带有通配符的文件名集。例如,*.txt
表示名称以.txt
结尾的所有文件。*
是代表任意字符串的通配符。另一个常见的通配符是问号(?),它代表一个字符。
路径提供了glob
和rglob
。后者用于递归通配。它在给定模式前添加**/
。
#!/usr/bin/python from pathlib import Path path = Path('C:/Users/Jano/Documents/pyprogs') for e in path.rglob('*.py'): print(e) # for e in path.glob('**/*.py'): # print(e)
该示例打印指定目录及其所有子目录中的所有Python文件。请注意,此类操作可能非常耗时。
for e in path.rglob('*.py'): print(e) # for e in path.glob('**/*.py'): # print(e)
这两个操作是等价的。
路径树
下面的例子是一个实用的程序,它以分层树结构输出指定目录的内容。
#!/usr/bin/python from pathlib import Path def tree(directory): print(f'+ {directory}') for path in sorted(directory.rglob('*')): depth = len(path.relative_to(directory).parts) spacer = ' ' * depth # print(f'{spacer}+ {path.name}') if path.is_file(): print(f'{spacer}f {path.name}') else: print(f'{spacer}d {path.name}') path = Path.home() / 'Downloads' tree(path)
程序以树状结构输出下载目录的内容。
按扩展名统计文件
在下面的示例中,我们按扩展名对所有文件进行计数。我们使用集合的
Counter
来完成任务。
#!/usr/bin/python import collections from pathlib import Path docs = Path.home() / 'Documents' files = [path.suffix for path in docs.iterdir() if path.is_file() and path.suffix] data = collections.Counter(files) print(data) for key, val in data.items(): print(f'{key}: {val}')
该示例对Documents目录中按扩展名分组的文件进行计数。
files = [path.suffix for path in docs.iterdir() if path.is_file() and path.suffix]
在列表理解中,我们确保路径对象是一个带有is_file
的文件并且该文件具有扩展名。文件可能没有扩展名;特别是在Unix系统上。
$ count_files.py Counter({'.txt': 7, '.pdf': 3, '.ini': 1, '.zip': 1, '.rtf': 1}) .pdf: 3 .txt: 7 .ini: 1 .zip: 1 .rtf: 1
路径读取文本
read_text
将文件内容作为字符串读取。文件打开然后关闭。可选参数与open
中的含义相同。
#!/usr/bin/python from pathlib import Path path = Path('words.txt') content = path.read_text() print(content)
该示例使用read_text
读取words.txt
文件的内容。
$ read_text.py blue forest sky ocean rabbit clue
合并两个文件
在下面的例子中,我们从两个文本文件中读取数据并合并它们
sky cup wind snow tree
这是words.txt文件。
blue brown strong early old
这是adjectives.txt文件。
#!/usr/bin/python import sys from pathlib import Path fname1 = sys.argv[1] fname2 = sys.argv[2] data1 = Path(fname1).read_text(encoding='utf-8').splitlines() data2 = Path(fname2).read_text(encoding='utf-8').splitlines() data = list(zip(data1, data2)) for e in data: print(' '.join(e))
我们将adjectives.txt与words.txt合并。
data1 = Path(fname1).read_text(encoding='utf-8').splitlines() data2 = Path(fname2).read_text(encoding='utf-8').splitlines()
我们从两个文件中读取数据并将它们分成几行。
data = list(zip(data1, data2))
我们压缩两个列表;我们得到一个元组对列表。
for e in data: print(' '.join(e))
最后,我们将每个元组对连接成最终字符串。
$ ./join_files.py adjectives.txt words.txt blue sky brown cup strong wind early snow old tree
路径读取文件打开
open
打开路径指向的文件,就像内置的open
函数一样。
#!/usr/bin/python from pathlib import Path path = Path('words.txt') with path.open() as f: lines = f.readlines() print(lines) for line in lines: print(line.rstrip())
该示例使用open
打开words.txt
文件并使用readlines
读取内容。
读取二进制文件的路径
可以使用read_bytes
读取二进制文件,例如图像。
#!/usr/bin/python from pathlib import Path import binascii from more_itertools import sliced path = Path('sid.jpg') hexed = binascii.hexlify(path.read_bytes()) mybytes = list(sliced(hexed, 2)) i = 0 for b in mybytes: print(b.decode("utf-8") , end=' ') i += 1 if (i % 30 == 0): print()
该示例读取JPEG图片并以十六进制表示将其打印到终端。
路径写入文本
write_text
以文本模式打开文件,向其中写入数据,然后关闭文件。
#!/usr/bin/python from pathlib import Path path = Path('myfile.txt') path.touch() path.write_text('This is myfile.txt')
该示例使用touch
创建一个新的空文件,并使用write_text
将一些文本数据写入文件。
新文章
内容管理系统通常会根据当前年份和月份将其新创建的文章放在目录结构中。下一个示例演示了这一点。
#!/usr/bin/python from pathlib import Path import datetime now = datetime.datetime.now() year = now.year month = now.month name = input('Enter article name:') path1 = Path('articles') / str(year) / str(month) path1.mkdir(parents=True) path2 = path1 / f'{name}.txt' path2.touch() print(f'Article created at: {path2}')
程序要求用户输入。它根据当前的年份和月份创建一个新的文本文件。
PythonPathlibPrettyTable示例
当我们处理文件和目录时,我们可以使用PrettyTable
模块以获得更好的输出。
#!/usr/bin/python from pathlib import Path import datetime from prettytable import PrettyTable path = Path('C:/Users/Jano/Documents/') pt = PrettyTable() pt.field_names = ["File name", "Size", "Created"] pt.align["File name"] = "l" pt.align["Size"] = "r" pt.align["Created"] = "l" for e in path.glob('**/*.txt'): created = datetime.datetime.fromtimestamp(e.stat().st_ctime) size = e.stat().st_size pt.add_row([e.name, size, f"{created:%Y-%m-%d}"]) print(pt)
该示例将Documents中的所有文本文件显示在一个漂亮的表格中。该表格包含三列:文件名、大小和创建日期。
$ simple_table.py +-------------------------------------------------------+-------+------------+ | File name | Size | Created | +-------------------------------------------------------+-------+------------+ | data.txt | 0 | 2019-02-27 | | eternal_return.txt | 10467 | 2019-03-03 | | potvrdenie.txt | 773 | 2019-01-14 | | text_processing.txt | 750 | 2019-02-18 | | website-inspire.txt | 62 | 2019-03-03 | | words.txt | 31 | 2018-12-30 | | Ãvod do Symfony.txt | 7613 | 2019-03-04 | | robots.txt | 240 | 2019-01-01 | | robots.txt | 240 | 2019-02-03 | ...
这是部分输出示例。
在本文中,我们介绍了标准的Pythonpathlib模块。
列出所有Python教程。