pathspec 是一个用于文件路径模式匹配的实用库。到目前为止,它只包含 Git 的 gitignore 模式匹配。
假设你有一个“Projects”目录,你想备份它,但只想备份某些文件,并根据某些条件忽略其他文件:
>>> from pathspec import PathSpec >>> # 用于选择文件的 gitignore 风格的模式,但我们是包含 >>> # 而不是忽略。 >>> spec_text = """ ... ... # 这是注释,因为行以哈希值开头:“#” ... ... # 包含当前目录以下的几个项目目录(及其所有后代)。 ... # 要仅引用一个目录,您必须以斜杠结尾:“/” ... /project-a/ ... /project-b/ ... /project-c/ ... ... # 模式可以通过在前面加上感叹号“!”来否定 ... ... # 忽略临时文件,这些文件以“~”开头或结尾,或以“.swp”结尾。 ... !~* ... !*~ ... !*.swp ... ... # 这些是 Python 项目,因此忽略测试中编译的 Python 文件。 ... !*.pyc ... ... # 忽略构建目录,但仅在项目目录正下方。 ... !/*/build/ ... ... """
PathSpec 类提供了模式实现的抽象,我们希望将我们的模式编译为“gitignore”模式。您可以将其称为已编译模式列表的包装器:
>>> spec = PathSpec.from_lines('gitignore', spec_text.splitlines())
如果我们想手动编译模式,我们可以直接使用 GitIgnoreBasicPattern 类。它在后台用于“gitignore”,内部将模式转换为正则表达式:
>>> from pathspec.patterns.gitignore.basic import GitIgnoreBasicPattern >>> patterns = map(GitIgnoreBasicPattern, spec_text.splitlines()) >>> spec = PathSpec(patterns)
PathSpec.from_lines() 是一个类方法,可以简化此操作。
如果您想从文件加载模式,也可以直接传递文件对象:
>>> with open('patterns.list', 'r') as fh:
>>> spec = PathSpec.from_lines('gitignore', fh)
您可以使用以下命令在整个目录树上执行匹配:
>>> matches = set(spec.match_tree_files('path/to/directory'))
或者,您可以对一组特定的文件路径执行匹配:
>>> matches = set(spec.match_files(file_paths))
或者检查单个文件是否匹配:
>>> is_matched = spec.match_file(file_path)
实际上,“gitignore”有两种实现。PathSpec 使用基本实现,并遵循 gitignore 文档中的模式。但是,Git 的行为与文档化模式不同。存在一些边缘情况,特别是,Git 允许包含已排除目录中的文件,这似乎与文档相矛盾。GitIgnoreSpec 处理这些情况,以更紧密地复制 Git 的行为:
>>> from pathspec import GitIgnoreSpec >>> spec = GitIgnoreSpec.from_lines(spec_text.splitlines())
您不需要为 GitIgnoreSpec 指定模式样式,因为它应该始终在内部使用 GitIgnoreSpecPattern。
在 Python 中对数千个文件运行大量正则表达式匹配会很慢。可以使用备用正则表达式后端来提高性能。PathSpec 和 GitIgnoreSpec 都接受 backend 参数来控制后端。默认值为“best”,会自动选择最佳可用后端。目前有 3 个后端。
“simple”后端是默认的,它简单地使用 Python 的 re.Pattern 对象,这些对象通常是正常的创建方式。当只有 1 或 2 个模式时,这可能是最快的。
“hyperscan”后端使用 hyperscan 库。Hyperscan 通常比“simple”快至少 2 倍,并且通常比“re2”慢。在模式数量为 1-25 的情况下,它可能比“re2”快。
“re2”后端使用 google-re2 库(不要与 PyPI 上的 re2 库混淆,后者不相关且已弃用)。Google re2 在模式数量很高时,通常比“simple”快得多,并且比“hyperscan”快 3 倍。
有关原生 Python 正则表达式和可选后端之间的比较,请参阅 benchmarks_backends.md。
默认情况下,GitIgnoreSpec(和 PathSpec)会积极匹配文件。要查找要保留的文件,并排除类似 .gitignore 的文件,您需要设置 negate=True 来翻转结果:
>>> from pathspec import GitIgnoreSpec
>>> spec = GitIgnoreSpec.from_lines([...])
>>> keep_files = set(spec.match_tree_files('path/to/directory', negate=True))
>>> ignore_files = set(spec.match_tree_files('path/to/directory'))
pathspec 在 Mozilla Public License Version 2.0 下获得许可。有关更多信息,请参阅 LICENSE 或 FAQ。
总而言之,您可以将 pathspec 用于任何闭源或开源项目,而不会影响较大作品的许可证,前提是您:
- 给予应有的赞扬,
- 并发布对 pathspec 所做的任何自定义更改。
pathspec 的源代码可在 GitHub 仓库 cpburnz/python-pathspec 中找到。
pathspec 可通过 PyPI 安装:
pip install pathspec
pathspec 也可以从源代码构建。将需要以下软件包:
- build (>=0.6.0)
然后,可以使用以下命令构建和安装 pathspec:
python -m build pip install dist/pathspec-*-py3-none-any.whl
可以安装以下可选依赖项:
- google-re2:启用可选的“re2”后端。
- hyperscan:启用可选的“hyperscan”后端。
- typing-extensions:改进了一些类型提示。
pathspec 的文档可在 Read the Docs 上找到。
完整的更改历史记录可在 CHANGES.rst 和 Change History 中找到。
升级指南可在 UPGRADING.rst 和 Upgrade Guide 中找到。
相关的项目 pathspec-ruby(由 highb 提供)提供了一个类似的库作为 Ruby gem。