一个用于递归解压缩多层嵌套压缩文件的Python库
Project description
Layer Peel
一个用于递归解压缩多层嵌套压缩文件的Python库。
✨ 特性
- 🔄 递归解压缩: 自动处理嵌套的压缩文件
- 📦 多格式支持: 支持 ZIP、TAR、TGZ、7Z、RAR 等格式
- 🚀 流式处理: 内存友好的流式解压缩
- 🎯 自动检测: 智能识别压缩文件格式
- 🛡️ 异常处理: 完善的错误处理和日志记录
- 🔧 命令行工具: 提供易用的CLI接口
- 📝 完整文档: 详细的API文档和使用示例
- ⚡ 现代开发: 使用 uv 进行极速依赖管理和构建
🚀 快速开始
安装
使用 pip 安装
pip install layer-peel
使用 uv 安装(推荐)
# 安装 uv(如果尚未安装)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 使用 uv 安装 layer-peel
uv add layer-peel
# 或者在临时环境中运行
uvx layer-peel --help
基本使用
作为Python库使用
from layer_peel import extract
# 简单使用 - 使用默认配置
with open('nested_archive.zip', 'rb') as f:
for file_data, file_path, mime_type in extract(f, 'nested_archive.zip'):
print(f"提取文件: {file_path}")
# 保存文件
with open(file_path, 'wb') as output:
for chunk in file_data:
output.write(chunk)
高级用法 - 自定义配置:
from layer_peel import extract
from layer_peel.types import ExtractConfig
from layer_peel.utils import lifespan
from layer_peel.ct import extract_funcs
# 创建自定义配置
config = ExtractConfig(
chunk_size=32768, # 自定义块大小
lifespan_manager=lifespan,
extract_funcs=extract_funcs,
)
# 使用自定义配置
with open('nested_archive.zip', 'rb') as f:
for file_data, file_path, mime_type in extract(f, 'nested_archive.zip', depth=10, config=config):
print(f"提取文件: {file_path}")
# 保存文件
with open(file_path, 'wb') as output:
for chunk in file_data:
output.write(chunk)
使用命令行工具
# 基本用法
layer-peel archive.zip
# 指定输出目录
layer-peel archive.zip -o /tmp/extracted
# 设置递归深度
layer-peel archive.zip -d 10
# 静默模式
layer-peel archive.zip --quiet
# 详细模式
layer-peel archive.zip --verbose
📖 详细文档
重要说明
extract 函数现在提供了两种使用方式:
- 简单使用: 直接调用
extract(data, source_path)使用默认配置 - 高级使用: 传入自定义的
ExtractConfig对象进行精确控制
这样设计的优势:
- 易于上手: 新用户可以直接使用,无需了解配置细节
- 高度可配置: 高级用户可以精确控制解压缩行为
- 向后兼容: 保持API的简洁性
- 更好的扩展性: 未来可以轻松添加新的配置选项
API 参考
extract(data, source_path, depth=5, config=None)
递归解压缩多层嵌套的压缩文件。
参数:
data: 输入数据,可以是字节流迭代器或文件对象source_path: 源文件路径,用于标识和日志记录depth: 最大递归深度,防止无限递归,默认5层config: ExtractConfig配置对象,可选。如果为None,使用默认配置
返回:
生成器,产生 (file_data, file_path, mime_type) 元组
示例:
简单使用:
from layer_peel import extract
with open('complex_archive.zip', 'rb') as f:
for file_data, file_path, mime_type in extract(f, 'complex_archive.zip'):
print(f"文件: {file_path}")
print(f"类型: {mime_type}")
# 处理文件数据
content = b''.join(file_data)
print(f"大小: {len(content)} 字节")
自定义配置:
from layer_peel import extract
from layer_peel.types import ExtractConfig
from layer_peel.utils import lifespan
from layer_peel.ct import extract_funcs
# 创建配置
config = ExtractConfig(
chunk_size=65536,
lifespan_manager=lifespan,
extract_funcs=extract_funcs,
)
with open('complex_archive.zip', 'rb') as f:
for file_data, file_path, mime_type in extract(f, 'complex_archive.zip', depth=5, config=config):
print(f"文件: {file_path}")
print(f"类型: {mime_type}")
# 处理文件数据
content = b''.join(file_data)
print(f"大小: {len(content)} 字节")
支持的格式
| 格式 | 扩展名 | 说明 |
|---|---|---|
| ZIP | .zip | 最常见的压缩格式 |
| TAR | .tar | Unix/Linux 归档格式 |
| TGZ/TAR.GZ | .tgz, .tar.gz | Gzip压缩的TAR |
| 7Z | .7z | 7-Zip压缩格式 |
| RAR | .rar | WinRAR压缩格式 |
高级用法
ExtractConfig 配置说明
ExtractConfig 是一个数据类,用于配置解压缩行为:
from layer_peel.types import ExtractConfig
from layer_peel.utils import lifespan
from layer_peel.ct import extract_funcs
config = ExtractConfig(
chunk_size=65536, # 读取数据的块大小,默认64KB
lifespan_manager=lifespan, # 生命周期管理器,用于进度跟踪
extract_funcs=extract_funcs, # 支持的压缩格式提取函数映射
format_path=lambda x: f"{x}!" # 可选:路径格式化函数
)
自定义生命周期管理器
from contextlib import contextmanager
from layer_peel import extract
from layer_peel.types import ExtractConfig
from layer_peel.ct import extract_funcs
@contextmanager
def custom_progress(path):
print(f"🚀 开始处理: {path}")
try:
yield
finally:
print(f"✅ 完成处理: {path}")
# 创建自定义配置
config = ExtractConfig(
chunk_size=32768, # 自定义块大小
lifespan_manager=custom_progress, # 自定义生命周期管理器
extract_funcs=extract_funcs,
)
with open('archive.zip', 'rb') as f:
for file_data, file_path, mime_type in extract(f, 'archive.zip', depth=10, config=config):
# 处理文件...
pass
处理编码问题
from layer_peel.utils import fix_encoding
# 修复文件名编码
raw_filename = b'\xe4\xb8\xad\xe6\x96\x87.txt'
decoded_filename = fix_encoding(raw_filename)
print(decoded_filename) # 输出: 中文.txt
检测文件类型
from layer_peel.utils import get_mime_type
with open('unknown_file', 'rb') as f:
data = f.read(1024) # 读取前1KB
mime_type = get_mime_type(data)
print(f"文件类型: {mime_type}")
🛠️ 开发
使用 uv 进行依赖管理
本项目使用 uv 作为Python包和项目管理工具,提供极快的依赖解析和安装速度。
安装 uv
# macOS 和 Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# 或者使用 pip 安装
pip install uv
环境设置
# 克隆仓库
git clone https://github.com/LaciaProject/layer_peel.git
cd layer-peel
# 使用 uv 创建虚拟环境(自动检测 Python 版本)
uv venv
# 激活虚拟环境
source .venv/bin/activate # Linux/macOS
# 或
.venv\Scripts\activate # Windows
# 安装项目依赖(包括开发依赖)
uv pip install -e ".[dev,test,docs]"
# 或者使用 uv sync 同步锁定的依赖
uv sync --all-extras
依赖管理
# 添加新的运行时依赖
uv add requests
# 添加开发依赖
uv add --dev pytest-xdist
# 添加可选依赖组
uv add --optional docs sphinx
# 移除依赖
uv remove requests
# 更新所有依赖到最新版本
uv lock --upgrade
# 更新特定依赖
uv lock --upgrade-package requests
# 查看依赖树
uv tree
# 检查依赖冲突
uv pip check
Python 版本管理
# 安装特定 Python 版本
uv python install 3.11 3.12
# 查看已安装的 Python 版本
uv python list
# 为项目固定 Python 版本
uv python pin 3.11
# 使用特定 Python 版本创建虚拟环境
uv venv --python 3.12
运行脚本和工具
# 在虚拟环境中运行命令
uv run python -m pytest
# 运行项目脚本
uv run layer-peel --help
# 临时运行工具(无需安装)
uvx ruff check src/
# 安装全局工具
uv tool install ruff
构建和发布
# 构建包
uv build
# 发布到 PyPI(需要配置认证)
uv publish
# 发布到测试 PyPI
uv publish --repository testpypi
锁文件管理
项目使用 uv.lock 文件来锁定精确的依赖版本,确保在不同环境中的一致性:
# 生成/更新锁文件
uv lock
# 从锁文件安装依赖
uv sync
# 仅安装生产依赖
uv sync --no-dev
# 安装特定依赖组
uv sync --extra docs
性能优势
使用 uv 相比传统工具的优势:
- 🚀 极速安装: 比 pip 快 10-100 倍
- 🔒 可靠锁定: 确保跨环境的一致性
- 💾 缓存优化: 全局缓存减少重复下载
- 🛠️ 统一工具: 替代 pip、pip-tools、virtualenv、poetry 等
- 🐍 Python 管理: 内置 Python 版本管理
传统开发方式(可选)
如果您更喜欢使用传统工具:
# 创建虚拟环境
python -m venv .venv
source .venv/bin/activate
# 安装开发依赖
pip install -e ".[dev]"
# 安装pre-commit钩子
pre-commit install
运行测试
使用 uv 运行测试:
# 运行所有测试
uv run pytest
# 运行测试并生成覆盖率报告
uv run pytest --cov=layer_peel --cov-report=html
# 运行特定测试
uv run pytest tests/test_extract.py
# 并行运行测试(需要安装 pytest-xdist)
uv run pytest -n auto
# 运行测试并显示详细输出
uv run pytest -v
# 仅运行失败的测试
uv run pytest --lf
代码格式化和检查
使用 uv 进行代码质量检查:
# 检查代码质量和格式
uv run ruff check src/ tests/
# 自动修复可修复的问题
uv run ruff check --fix src/ tests/
# 格式化代码
uv run ruff format src/ tests/
# 类型检查
uv run mypy src/
# 运行所有检查(推荐在提交前运行)
uv run pre-commit run --all-files
一键开发环境设置
为了简化开发环境设置,您可以使用以下一键命令:
# 完整的开发环境设置
git clone https://github.com/LaciaProject/layer_peel.git && \
cd layer-peel && \
uv venv && \
source .venv/bin/activate && \
uv sync --all-extras && \
pre-commit install && \
echo "✅ 开发环境设置完成!"
🤝 贡献
我们欢迎各种形式的贡献!请查看 CONTRIBUTING.md 了解详细信息。
贡献指南
- Fork 这个仓库
- 创建你的特性分支 (
git checkout -b feature/AmazingFeature) - 提交你的更改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 打开一个 Pull Request
📝 更新日志
查看 CHANGELOG.md 了解版本更新历史。
📄 许可证
本项目采用 MIT 许可证 - 查看 LICENSE 文件了解详情。
🙏 致谢
- python-magic - 文件类型检测
- chardet - 字符编码检测
- py7zr - 7Z格式支持
- rarfile - RAR格式支持
- stream-unzip - 流式ZIP解压
📞 支持
如果你遇到问题或有疑问:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file layer_peel-0.1.0.tar.gz.
File metadata
- Download URL: layer_peel-0.1.0.tar.gz
- Upload date:
- Size: 23.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5031b303cdaf73febfdd58bc2eb14c64deff5604602834b774a52cf1e9fab628
|
|
| MD5 |
f7039611b364e36191183429ad6b70d3
|
|
| BLAKE2b-256 |
5b09abfc0f3ca67c285106b7e21548d4e1f49aeb235f0e92f4552f1d8e225a11
|
Provenance
The following attestation bundles were made for layer_peel-0.1.0.tar.gz:
Publisher:
release.yml on LaciaProject/layer_peel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
layer_peel-0.1.0.tar.gz -
Subject digest:
5031b303cdaf73febfdd58bc2eb14c64deff5604602834b774a52cf1e9fab628 - Sigstore transparency entry: 238861087
- Sigstore integration time:
-
Permalink:
LaciaProject/layer_peel@b7c559796d3824fb70f2fab3c9da9a47df93ee81 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/LaciaProject
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b7c559796d3824fb70f2fab3c9da9a47df93ee81 -
Trigger Event:
push
-
Statement type:
File details
Details for the file layer_peel-0.1.0-py3-none-any.whl.
File metadata
- Download URL: layer_peel-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f4567c1f9405f12b7af2ecb4bd0adcfeede58e26c15b3d084bc9e6bfebfb7d87
|
|
| MD5 |
4849dc8ce86ae4963baf2ce90fa1ca92
|
|
| BLAKE2b-256 |
b1dbbbd8ab5d4f3c51f9776bd383194606f3b8fb96990cf9cee7ed04f26764ee
|
Provenance
The following attestation bundles were made for layer_peel-0.1.0-py3-none-any.whl:
Publisher:
release.yml on LaciaProject/layer_peel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
layer_peel-0.1.0-py3-none-any.whl -
Subject digest:
f4567c1f9405f12b7af2ecb4bd0adcfeede58e26c15b3d084bc9e6bfebfb7d87 - Sigstore transparency entry: 238861089
- Sigstore integration time:
-
Permalink:
LaciaProject/layer_peel@b7c559796d3824fb70f2fab3c9da9a47df93ee81 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/LaciaProject
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b7c559796d3824fb70f2fab3c9da9a47df93ee81 -
Trigger Event:
push
-
Statement type: