【Python开发必读】:pkg_resources包管理进阶教程,打造高效代码架构
发布时间: 2024-10-10 00:01:01 阅读量: 216 订阅数: 33 ![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![](https://csdnimg.cn/release/wenkucmsfe/public/img/col_vip.0fdee7e1.png)
![PDF](https://csdnimg.cn/release/download/static_files/pc/images/minetype/PDF.png)
Python使用pip安装报错ModuleNotFoundError: No module named ‘pkg_resources’的解决方法
![【Python开发必读】:pkg_resources包管理进阶教程,打造高效代码架构](https://cdn.activestate.com/wp-content/uploads/2020/08/Python-dependencies-tutorial-1024x512.png)
# 1. pkg_resources包管理概述
在现代Python项目中,有效地管理和组织项目依赖成为了提高开发效率和维护性的关键。`pkg_resources`是Python包分发工具`setuptools`中的一个模块,它提供了一种方便的方式来管理包的依赖和资源。本章将从宏观角度概述`pkg_resources`的作用、使用场景以及它如何在项目依赖管理中发挥作用。
`pkg_resources`为开发者提供了一种简单而强大的方式来查询、管理和使用Python包资源,使得项目能够自动定位和加载包及其依赖,从而简化了跨平台应用的打包和分发过程。它不仅解决了Python包之间的依赖问题,还支持高级的资源发现机制,使得应用能够轻松地访问和利用这些资源。
在深入探讨`pkg_resources`的具体使用之前,有必要了解其背后的核心概念和原理。在下一章,我们将详细了解如何安装和初始化`pkg_resources`,以及如何利用它的依赖管理功能来优化我们的项目。
# 2. pkg_resources包基础使用
## 2.1 安装和初始化pkg_resources包
### 2.1.1 如何在项目中安装pkg_resources
在Python项目中,使用pkg_resources通常不需要单独安装,因为它是setuptools包的一部分,而setuptools是大多数Python项目所依赖的工具。当您使用pip安装任何包时,setuptools将自动被安装到您的系统中。
但如果您需要确保pkg_resources是最新版本,或者您想要手动安装它,可以通过以下命令进行:
```sh
pip install -U setuptools
```
通过执行上述命令,您的项目环境将包括最新版本的pkg_resources,这样就可以在项目中使用它提供的资源管理功能了。
### 2.1.2 初始化pkg_resources环境
初始化pkg_resources环境通常在您的脚本或者模块的入口点进行。初始化过程包括获取当前包信息以及准备包资源的读取。这在使用pkg_resources作为资源管理工具时尤其重要。
下面是一个如何初始化pkg_resources的示例:
```python
import pkg_resources
# 获取当前包的信息
entry_point = pkg_resources.EntryPoint.parse('foo = bar:main', dist='foo')
entry_point.load()
# 获取项目的包信息
my_dist = pkg_resources.get_distribution('my_package')
# 获取所有已安装包的信息
all_packages = [pkg.key for pkg in pkg_resources.working_set]
# 初始化资源访问
res = pkg_resources.resource_string(my_dist, 'my_package/some_file.txt')
```
在这段代码中,我们首先解析了一个入口点(entry point),这个概念在Python包开发中用于指定包的启动代码。随后,通过`get_distribution`获取当前包的信息,`working_set`则返回一个包含所有已安装包的集合。最后,通过`resource_string`方法获取当前包内的一个资源文件的内容。
## 2.2 pkg_resources包的依赖管理
### 2.2.1 依赖项的声明和解析
pkg_resources提供了一种简单的方式来声明和解析项目的依赖项。这通常在项目的`setup.py`文件中完成。
以下是一个如何声明依赖项的例子:
```python
setup(
...
install_requires=[
'requests >= 2.18.4',
'numpy >= 1.14.2',
],
...
)
```
在这个例子中,`install_requires`字段告诉setuptools,当安装这个包时,还需要安装`requests`和`numpy`这两个包。同时,还指定了版本要求,确保安装的版本不会低于指定的版本。
pkg_resources会自动处理这些依赖,并解析出具体的版本号,确保安装时不会产生冲突。
### 2.2.2 解决依赖冲突的策略
当项目声明了多个依赖项,且这些依赖项之间存在版本冲突时,pkg_resources和setuptools会尝试自动解决冲突。具体的解决策略包括:
- 根据指定的版本范围选择最大兼容的版本。
- 如果无法兼容,则会抛出错误提示,要求用户解决冲突。
下面是一个具体的依赖解析例子:
```python
from pkg_resources import resolve_distribution
try:
dist = resolve_distribution(
requires='requests>=2.0,<=3.0; extra == "web"',
extras={ 'web': ['django'] }
)
except VersionConflict as e:
# 处理依赖冲突
print(f'冲突的依赖信息: {e.extras_require}')
```
在上面的代码中,`resolve_distribution`尝试解析一个带有额外条件的依赖项。如果无法解析,则抛出`VersionConflict`异常,开发者可以根据异常信息来解决依赖冲突。
## 2.3 pkg_resources包的资源发现机制
### 2.3.1 资源文件的定位和使用
pkg_resources提供了一种机制,使得在Python包中访问内部资源文件变得简单。资源文件可以是图像、数据文件、模板等,它们通常被打包在Python包中,但并不直接位于Python的模块搜索路径上。
资源文件可以通过包名和相对路径来访问,例如:
```python
from pkg_resources import resource_string
# 获取当前包中某个资源文件的内容
data = resource_string(__name__, 'my_package/my_resource.txt')
```
在这个例子中,`resource_string`函数会返回指定资源文件的字符串内容。`__name__`表示当前包的名称,`'my_package/my_resource.txt'`是相对于当前包目录的资源路径。
### 2.3.2 高级资源访问技术
pkg_resources还支持更高级的资源访问技术,比如访问包含资源的文件夹。这在动态加载资源时非常有用。以下是一个如何访问资源文件夹的例子:
```python
from pkg_resources import resource_filename
# 获取资源文件夹的绝对路径
folder_path = resource_filename(__name__, 'my_package/resources')
# 现在folder_path变量包含资源文件夹的路径,可以用来访问里面的文件
```
在这个例子中,`resource_filename`函数返回指定资源文件夹的绝对路径。开发者可以使用这个路径来动态加载资源文件夹中的文件。
通过这种方式,您可以轻松地管理和访问项目中的所有资源,而无需担心资源文件的具体位置,这对于大型项目和复杂的资源管理尤为有用。
# 3. pkg_resources包的高级特性
## 3.1 插件系统的实现
### 3.1.1 创建和注册插件
插件系统提供了一种机制,允许第三方开发者或内部团队扩展应用程序的功能,而无需修改应用程序的核心代码。使用pkg_resources包实现插件系统时,需要定义清晰的插件接口和生命周期管理。
首先,我们需要创建插件类并为其编写必要的接口实现。以下是一个简单的插件类的例子:
```python
class SamplePlugin:
def __init__(self):
print("SamplePlugin initialized")
def execute(self):
print("Executing SamplePlugin...")
```
接下来,需要将该插件注册到pkg_resources包能够识别的位置。通常,这是在 setuptools 的 `entry_points` 中配置:
```python
from setuptools import setup
setup(
name='sample_package',
# ... 其他配置项
entry_points={
'sample_package.plugins': [
'sample_plugin = sample_module:SamplePlugin',
],
},
)
```
在这里,`entry_points` 字典中定义了一个组名 `sample_package.plugins`,并列出了插件模块和对应的插件类路径。这样,pkg_resources包就能通过这个组名查找并加载所有已注册的插件。
### 3.1.2 动态加载插件的机制
一旦插件被注册,我们可以使用pkg_resources包提供的机制动态加载和使用插件,而不必在运行时包含插件代码。这可以在主程序中通过以下方式进行:
```python
import pkg_resources
# 加载所有插件
for entry_point in pkg_resources.iter_entry_points('sample_package.plugins'):
plugin = entry_point.load()
plugin.execute()
```
在这段代码中,`iter_entry_points` 函数用于迭代指定组名的所有条目点,`load` 方法加载并初始化对应的插件类。这种方式非常灵活,可以按需加载插件,节省资源。
## 3.2 分布式包管理的实践
### 3.2.1 包的打包与分发
在现代软件开发中,将代码打包并分发至用户或第三方是一个重要步骤。使用pkg_resources和setuptools可以有效地打包和分发Python包。
打包过程通常涉及创建一个包含 `setup.py` 文件的目录结构。`setup.py` 文件包含了打包和安装过程中所需的所有信息,如包名、版本、依赖项等。
```python
from setuptools import setup, find_packages
setup(
name='my_package',
version='1.0.0',
packages=find_packages(),
# ... 其他配置项
)
```
打包完成后,可以使用 `python setup.py sdist` 或 `python setup.py bdist_wheel` 来生成源码分发包(sdist)或wheel分发包。这些分发包可以上传到PyPI,使用pip等工具安装。
### 3.2.2 撰写setup.py的最佳实践
撰写 `setup.py` 文件时,应该遵循一些最佳实践以保证打包过程的顺利进行:
- 使用 `find_packages()` 自动发现并包含所有包。
- 维护清晰的依赖关系,包括开发依赖。
- 为包添加元数据,如作者、邮箱、URL和许可证。
- 提供长描述、分类和关键词等信息以提高包的可搜索性。
- 为不同平台和Python版本提供构建兼容性。
下面是一个更复杂的 `setup.py` 文件示例:
```python
from setuptools import setup, find_packages
setup(
name='my_package',
version='1.0.0',
description='A sample package with comprehensive setup.py',
long_description=open('README.md').read(),
long_description_content_type='text/markdown',
author='Author Name',
author_email='***',
url='***',
packages=find_packages(),
install_requires=[
'requests',
'beautifulsoup4',
],
extras_require={
'dev': [
'pytest',
'flake8',
],
},
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7',
'License :: OSI Approved :: MIT License',
],
python_requires='>=3.6',
)
```
## 3.3 集成第三方服务和库
### 3.3.1 集成第三方服务的方法
集成第三方服务是构建现代应用程序不可或缺的一部分。第三方服务可以是API、SaaS、或者其他类型的网络服务。在Python项目中集成第三方服务时,pkg_resources可以用来管理这些服务的Python客户端库。
首先,你需要找到合适的第三方服务客户端库。可以使用 `pip search` 或在PyPI上搜索需要的服务库。然后,在 `setup.py` 的 `install_requires` 部分添加对应的依赖。
例如,如果你需要集成一个天气服务API,你可以添加 `requests` 库作为依赖,因为它通常被用作HTTP请求的客户端:
```python
# 在 setup.py 中
install_requires=[
'requests',
# ... 其他依赖项
]
```
### 3.3.2 管理第三方库依赖
管理第三方库依赖通常涉及到版本控制和兼容性测试。pkg_resources可以辅助完成这一工作,提供对依赖项的解析功能。
为了确保依赖项的一致性,你需要指定库的版本范围:
```python
# 在 setup.py 中
install_requires=[
'requests>=2.23.0,<3.0',
# ... 其他依赖项
]
```
在 `setup.py` 文件中指定明确的版本范围可以减少运行时出现的版本不匹配问题。此外,使用虚拟环境和自动化测试流程来验证依赖项的兼容性是最佳实践。
为了方便管理依赖,还可以使用 `pip-tools` 等工具将依赖项固定到特定版本,并生成 `requirements.txt` 文件,供CI/CD管道或部署脚本使用。这样可以确保项目环境的一致性。
```bash
pip install pip-tools
pip-compile -r requirements.in
```
其中 `requirements.in` 文件包含了依赖项的概览,而 `requirements.txt` 将包含具体的、经过解析的依赖版本。
通过这种方式,第三方库的集成和管理变得更加规范化和透明化。
# 4. pkg_resources包管理在项目中的应用
## 4.1 代码架构优化策略
### 4.1.1 模块化和组件化的优势
模块化和组件化是现代软件开发中提高代码复用性、可维护性和可扩展性的关键策略。它们允许我们将一个复杂的系统分解为更小、更易管理的单元,每个单元都可以独立开发和测试。模块化侧重于代码的组织和划分,而组件化则更强调独立功能的实现和封装。通过模块化和组件化,开发者能够:
- **提高开发效率**:独立开发和测试各个组件,提升并行工作的可能性,缩短开发周期。
- **增强代码可维护性**:模块和组件的边界清晰,便于理解代码结构,修改和升级时影响范围有限。
- **促进代码复用**:标准的接口和交互协议使得各个模块或组件可以跨项目复用。
- **简化系统扩展**:通过增加或修改模块和组件,系统可灵活扩展新功能。
### 4.1.2 使用pkg_resources优化项目结构
pkg_resources提供了一套丰富的API来管理Python包和它们的依赖关系。利用pkg_resources,我们可以优化项目结构,实现高效的模块化和组件化。首先,通过定义清晰的依赖关系声明,pkg_resources能够自动处理依赖项的安装和更新。这样,开发者就可以将主要精力集中在业务逻辑的实现上,而不是环境配置上。其次,pkg_resources的资源发现机制允许项目中的模块或组件访问所需的资源文件,从而使得模块化更为简洁。以下是利用pkg_resources优化项目结构的步骤:
- **定义项目的包和依赖**:在setup.py文件中明确列出所有包及其依赖关系。
- **利用动态加载机制**:借助pkg_resources的插件机制,可以在运行时动态加载和更新插件。
- **实现资源的集中管理**:通过pkg_resources的资源发现功能,集中管理和访问项目中的资源文件,例如配置文件、数据文件等。
- **自动化依赖解析和冲突解决**:pkg_resources能够自动解析依赖关系并处理冲突,减少人工干预。
## 4.2 自动化构建和测试流程
### 4.2.1 利用pkg_resources自动化构建过程
在构建自动化流程中,pkg_resources可以承担多个关键角色。首先,它可以作为依赖管理工具,在构建前确保所有依赖已经安装并处于正确的版本。其次,pkg_resources可以通过读取项目的setup.py来动态生成所需的构建脚本。借助其插件系统,pkg_resources还可以集成其他构建工具和任务执行器,如 tox、Invoke 等,从而实现复杂的构建流程。
自动化构建流程的步骤大致如下:
1. **定义项目依赖**:在setup.py文件中声明项目的所有依赖。
2. **配置构建工具**:使用pkg_resources提供的API配置自动化构建工具。
3. **集成构建任务**:利用pkg_resources插件机制集成各种构建任务,如编译、打包等。
4. **测试依赖环境**:构建过程前运行依赖检查,确保所有必需的依赖都已安装。
5. **触发构建过程**:自动化触发整个构建流程, pkg_resources将自动处理所有依赖项。
6. **监控和记录构建状态**:构建过程中的每一步都被记录下来,便于问题追踪和历史比较。
### 4.2.2 集成测试框架的实现
自动化测试是软件开发中不可或缺的部分,pkg_resources能够和测试框架(如pytest、nose)无缝集成,以实现更加强大的测试流程。利用pkg_resources的依赖管理能力,可以确保测试环境中正确安装了所有必需的包,并且版本符合测试要求。
集成测试框架的步骤包括:
1. **配置测试依赖**:在setup.py文件中明确指出哪些包是用于测试的。
2. **编写测试用例**:根据项目需求编写测试用例,测试用例应包括单元测试和集成测试。
3. **运行测试命令**:使用pkg_resources提供的命令行接口运行测试用例。
4. **依赖注入**:通过pkg_resources的API在运行时注入所需的测试依赖。
5. **收集和分析测试结果**:测试执行后,自动收集测试报告,并使用工具进行分析。
## 4.3 包版本管理和更新机制
### 4.3.1 版本控制的重要性
在软件开发过程中,版本控制不仅是跟踪和记录更改的机制,而且是保证软件质量的关键因素。良好的版本控制策略允许开发者:
- **跟踪历史更改**:方便回溯到之前的版本,了解各个版本之间的差异。
- **分支开发和合并**:支持多线程开发,例如特性开发、bug修复等。
- **避免代码冲突**:确保多人协作时代码的整合性和一致性。
- **提供稳定的版本发布**:确保发布的版本可追溯、可控并且稳定。
### 4.3.2 实现自动化的版本更新和发布
利用pkg_resources的包管理功能可以实现自动化版本控制和发布。具体实现方法包括:
- **使用setuptools_scm进行版本管理**:setuptools_scm是一个用于管理和声明项目版本的工具,能够根据Git或其他版本控制系统的标签自动生成版本号。
- **自动化版本更新**:在构建和发布过程中,通过脚本自动化更新版本号,确保每次发布的版本号都是唯一的。
- **依赖项版本控制**:在setup.py中声明依赖项的版本范围,确保项目依赖的稳定性。
- **集成到持续集成/持续部署(CI/CD)流程**:将版本管理作为CI/CD流程的一部分,每次代码提交或合并到主分支时自动触发版本更新和构建流程。
```python
# 示例代码:使用setuptools_scm进行版本管理的setup.py配置
from setuptools import setup
setup(
use_scm_version={
'write_to': 'my_package/_version.py',
'write_to_template': '__version__ = "{version}"',
},
packages=['my_package'],
# 其他配置项...
)
```
在上述代码中,`use_scm_version`字段表明我们将使用setuptools_scm工具来自动生成和管理版本号。`write_to`参数定义了版本号文件的路径和文件名,而`write_to_template`定义了文件内容模板。通过这种方式,每次构建时都会自动更新版本号。
在自动化测试和发布流程中,pkg_resources提供了一系列命令行工具,如`python setup.py sdist`用于生成源代码发行包,`python setup.py bdist_wheel`用于生成wheel文件等,这些工具可以被集成到CI/CD流程中,实现完全自动化的软件构建和发布过程。
# 5. 实践案例与故障排除
## 5.1 典型案例分析
### 5.1.1 案例一:如何使用pkg_resources管理大型项目依赖
大型项目往往伴随着复杂的依赖关系,使用pkg_resources可以有效地管理这些依赖,保证项目能够在不同的环境中稳定运行。一个典型的案例是Django框架的依赖管理,Django在安装过程中会自动解析`requirements.txt`文件,利用pkg_resources来确保所有必需的依赖项被正确安装。
在这个案例中,首先需要创建一个`setup.py`文件,它会声明项目所有必需的依赖。然后,通过编写一个安装脚本或使用pip,可以自动化安装和配置这些依赖。为了应对依赖冲突,pkg_resources提供了一套机制来解析最合适的依赖版本,并以日志形式记录下它的决策过程,让开发者可以追踪可能的问题。
### 5.1.2 案例二:实现跨平台的资源分发
跨平台的资源分发要求包管理工具不仅能够处理不同平台的特定文件格式,还要能够灵活地适应不同操作系统的差异。一个典型的实现是PyInstaller工具,它使用pkg_resources来识别和打包应用程序所需的资源文件,从而实现在Windows、Linux和macOS等多种操作系统上的可执行文件打包。
为了适应跨平台的需求,PyInstaller分析了应用程序的运行时需求,通过pkg_resources获取了必需的二进制文件和库文件,并将它们包含在最终的分发包中。这保证了用户在不同平台上安装和运行应用程序时,都能获得相同的体验。
## 5.2 常见问题及解决方案
### 5.2.1 解决依赖冲突的方法
在包管理的过程中,依赖冲突是一个常见的问题。pkg_resources通过一套内置的依赖解析器来解决这些冲突,它遵循PEP 3002和PEP 3010的规定,提供了依赖声明和解析的机制。在解析依赖时,它会查找依赖树中满足所有依赖要求的最高版本,尽可能避免版本冲突。
如果在依赖解析过程中出现了冲突,pkg_resources会抛出`DistributionNotFound`或`VersionConflict`异常。解决这类问题的常见方法包括手动指定依赖版本、使用兼容的第三方包管理器插件,或者更新`setup.py`中的依赖声明。
### 5.2.2 包管理中的性能调优技巧
由于大型项目可能涉及到大量的依赖和资源文件,包管理的性能调优变得非常重要。使用pkg_resources时,可以通过缓存依赖信息、并行处理依赖解析任务来提高效率。此外,合理的文件组织结构和资源定位策略也是提升性能的关键。
性能调优的另一个方面是优化`setup.py`文件。使用更高效的数据结构和算法来处理依赖信息,可以减少pkg_resources在运行时的计算量。在必要时,还可以通过编写自定义的解析器或者优化代码来进一步提升包管理性能。
## 5.3 高级故障排除技巧
### 5.3.1 使用日志和调试信息定位问题
在pkg_resources的使用过程中,当遇到问题时,首先应当检查日志和调试信息。pkg_resources通常会在控制台输出关于依赖解析和资源发现过程的详细信息。开发者可以通过设置不同的日志级别,来获取不同深度的日志信息。
```python
import logging
logging.basicConfig(level=logging.DEBUG)
# 继续使用pkg_resources的API进行操作
```
通过分析日志,开发者可以了解pkg_resources是如何处理依赖项的,以及在何处可能出现了问题。例如,如果某个包声明了版本范围,但实际安装的包不满足这个范围,pkg_resources会记录下原因。
### 5.3.2 高级调试工具和插件的介绍
除了Python内置的日志系统之外,还有一些高级的调试工具和插件可以用于更深入地分析pkg_resources的内部行为。一些流行的Python开发工具,如PyCharm或者VSCode,都提供了强大的调试和性能分析插件,它们可以集成到pkg_resources的使用过程中。
此外,还有一些第三方库如`py-spy`,可以用来生成Python程序的运行时堆栈信息。通过这些工具,开发者可以更细致地观察pkg_resources在处理依赖和资源时的行为。
```bash
pip install py-spy
py-spy dump --pid <Python进程ID>
```
这个命令可以帮助开发者实时获取Python进程的调用堆栈,从而对pkg_resources的行为做出更准确的分析。
# 6. pkg_resources包管理的未来趋势
## 6.1 包管理技术的发展方向
随着软件开发复杂性的增加,包管理技术的发展方向也在不断演进,以适应新的挑战和需求。
### 6.1.1 现代Python项目中的包管理趋势
在现代Python项目中,包管理的趋势正向以下方向发展:
- **轻量级依赖声明**:随着包管理工具如Poetry和pipenv的出现,项目开发者可以轻松地声明项目依赖,并通过环境隔离确保项目依赖的正确性。
- **依赖冲突解决**:自动化的依赖冲突解决机制是未来包管理工具的关键特性,可以大大减少人工干预的需要。
- **跨平台兼容性**:越来越多的包管理工具致力于提供良好的跨平台支持,让开发者无论在Windows、Linux还是macOS上都能保持一致的工作体验。
### 6.1.2 pkg_resources与新兴包管理工具的对比
pkg_resources作为早期的包管理工具之一,在某些方面已经显示出其局限性。而新兴的包管理工具如Poetry或pipenv提供了更为全面的管理功能:
- **环境管理**:新兴工具允许为每个项目创建独立的虚拟环境,而pkg_resources本身并不直接提供环境隔离功能。
- **依赖解析**:Poetry和pipenv使用了更为先进的算法来解决依赖冲突问题,而pkg_resources的解析策略可能需要在用户的介入下才能解决复杂的依赖问题。
- **用户友好性**:这些新兴工具通常具有更加友好的用户界面和用户体验,例如直观的命令行接口和更好的错误处理机制。
## 6.2 推动代码架构高效性的新思路
### 6.2.1 包管理在微服务架构中的应用前景
随着微服务架构在企业级应用中的普及,包管理工具也开始适应这种分布式、松耦合的架构模式。这将带来一些新的趋势:
- **服务发现与依赖管理**:微服务架构中,服务间的依赖关系需要动态管理,包管理工具可能会集成或与服务发现工具结合,提供一种服务间依赖自动化的解决方案。
- **容器化和编排**:容器化技术如Docker和编排工具如Kubernetes的使用逐渐成为标准,包管理工具未来可能需要提供对容器镜像构建和管理的支持。
### 6.2.2 代码架构的自动化与智能化发展
未来代码架构的发展将更加注重自动化和智能化:
- **自动化重构**:利用包管理工具提供的API,可以实现代码的自动重构和迁移,减少人为操作错误。
- **智能代码维护**:通过机器学习等人工智能技术,包管理工具可能能够预测项目的未来依赖,提前进行依赖更新和优化,从而提高代码维护的效率。
总之,随着技术的进步和开发需求的演变,pkg_resources和其它包管理工具都将朝着提供更高效、更智能的代码架构管理方向发展。开发者需要不断学习和适应这些新趋势,以保持竞争力。
0
0
相关推荐
![gz](https://img-home.csdnimg.cn/images/20210720083447.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![rar](https://img-home.csdnimg.cn/images/20241231044955.png)
![-](https://img-home.csdnimg.cn/images/20210720083447.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![zip](https://img-home.csdnimg.cn/images/20241231045053.png)
![whl](https://img-home.csdnimg.cn/images/20250102104920.png)