假如在同一级目录下有两个python文件(即python模块),那么这两个模块不需要安装也能相互进行
import引用,但是不在同级目录下甚至不在同一项目中的模块怎么做到相互引用呢?
setuptools是python自带用于打包构建的工具,使用此工具可打包出可供import引用的模块或者可供他人安装的wheel包。
官方文档:setuptools
首先需要在项目根目录创建setup.py,用于设置setuptools的构建配置。这里是直接使用的setuptools.setup()函数进行配置,官方推荐的方式是使用setup.cfg配置文件。
import setuptools
setuptools.setup(name='test-tool', # 扩展功能包名称py_modules=['test'] # 打包模块名称,对应test.py,安装包之后使用此名称进行import
)
切换到项目根目录,通过pip install .命令进行安装。安装成功后,就可以在其他python文件中import模块并调用该模块下的函数。
这里同样是使用setuptools.setup()函数方式进行配置,如下。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import setuptoolssetuptools.setup(name='test-tool',version='1.0.0',description='Description.',author='San',author_email='San@163.com',package_dir={"": "src"}, # 打包目录packages=setuptools.find_packages(where='src') # 搜索存在__init__.py打包文件夹
)
使用pip wheel .打包后会在当前目录生成*.whl文件,将这个文件提供给其他人,其他人通过pip install *.whl就能将此安装包安装到扩展库。
关于打包配置需要说明以下几点:
find_packages()只会搜索目录下包含__init__.py文件的目录进行打包。find_packages()可以设置打包剔除目录:setuptools.find_packages(exclude=['additional*']) # 剔除additional目录
.whl包和python包的概念:D:\python3.10\Lib\site-packages路径下出现python扩展功能包,注意D:\python3.10为python在本机的安装目录。├── src
│ └── mypkg
│ ├── __init__.py
│ └── tool1.py
├── setup.py
└── setup.cfg
./build/lib目录,在该目录下的模块才会被打进.whl安装包。setup.py clean清除临时打包目录。报错usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
wheel工具,实际在执行时用的指令是setup.py install。pip install wheel安装wheel,其次可以使用传统指令python setup.py bdist_wheel去打包。造成此错误的原因是配置打包目录src时没有同时设置find_packages()。正确示例如下。
package_dir={"": "src"},
packages=setuptools.find_packages(where='src')
文件夹src与setup.py不在同级目录下时会出现此错误,需将setup.py移至与src文件夹同级目录。
此问题也是个大坑,找了很久原因,最后发现是模块名称(也就是python文件)命名中包含"-",不符合Python编写规范导致的。
python文件只能以
英文小写命名,单词间可以用下划线。
pip list # 查看已安装扩展包列表
pip uninstall test-tool # 卸载扩展包
pip wheel . # 打包构建
pip install cert_kit-1.0.0-py3-none-any.whl # 安装扩展包
pip install -e . # 调用模块下的最新文件安装
本文以个人经验总结而成,内容有误的地方还请读者指正。