如何将本地whl文件纳入tar.gz包并实现跨环境正常安装?
本地私有Wheel依赖的Python包打包问题
项目结构
hardware_tools/ ├─ support/ │ ├─ __init__.py │ ├─ arena_api-2.3.3-py3-none-any.whl ├─ __init__.py ├─ scripts.py setup.py
问题描述
我有一个名为hardware_tools的Python项目,需要打包成可分发的tar.gz文件。项目依赖一个无法从PyPI/GitHub获取的私有wheel包arena_api-2.3.3-py3-none-any.whl,已将其放在项目的support目录下。
本地执行python setup.py install和python setup.py sdist都正常,但把生成的tar.gz拿到其他同版本Python环境安装时,报错:
ERROR: <WHEEL PATH>\arena_api-2.3.3-py3-none-any.whl is not a valid wheel filename.
尝试过按PEP 427修改wheel文件名、更换其他wheel文件,错误依旧;移除wheel相关配置后,tar.gz能正常安装但缺少依赖。
当前setup.py代码
import io, os, sys from shutil import rmtree from setuptools import (find_packages, setup, Command) # Metadata NAME = 'hardware_tools' DESCRIPTION = 'Module to maintain control of hardware tools including cameras, stages, etc.' URL = '' EMAIL = '' AUTHOR = '' REQUIRES_PYTHON = '>=3.8.*' VERSION = '2.0.1' # Create paths here = os.path.abspath(os.path.dirname(__file__)) here_support = os.path.join(here, "hardware_tools\\support") wheel_path = os.path.join(here_support, "arena_api-2.3.3-py3-none-any.whl") # Required or optional package dependencies REQUIRED = [ "Pillow", "PIPython", "RsInstrument", "aardvark-py", "keyboard", "labjack-ljm", "mecademicpy", "numpy==1.24.4", "pylablib", "pymba", "pyueye", "screeninfo", "seabreeze", "thorlabs-apt", "opencv-contrib-python", "matplotlib", "arena_api @ file://localhost/%s" % wheel_path ] try: with io.open(os.path.join(here, 'README.txt'), encoding='utf-8') as f: long_description = '\n' + f.read() except FileNotFoundError: long_description = DESCRIPTION # Load __version__.py as a dictionary. about = {} if not VERSION: project_slug = NAME.lower().replace("-", "_").replace(" ", "_") with open(os.path.join(here, project_slug, '__version__.py')) as f: exec(f.read(), about) else: about['__version__'] = VERSION # Setup project setup( name=NAME, version=about['__version__'], description=DESCRIPTION, long_description=long_description, long_description_content_type="text/markdown", author=AUTHOR, author_email=EMAIL, python_requires=REQUIRES_PYTHON, url=URL, packages=find_packages(exclude=["tests", "*.tests", "*.tests.*", "tests.*"]), dependency_links=[wheel_path], data_files=[("support", ["hardware_tools\\support\\config.json", "hardware_tools\\support\\aardvark.dll", wheel_path.split(here)[1][1:]])], install_requires=REQUIRED, include_package_data=True, license="MIT", classifiers=[ "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy" ], cmdclass={ "upload": UploadCommand, }, )
限制条件
- 无法通过网络下载该wheel(需厂商账号)
- 不能将该wheel上传至PyPI(知识产权风险)
解决方法
方案1:依赖声明调整+Post-Install脚本自动安装私有Wheel
- 移除
install_requires中的本地Wheel引用:从REQUIRED列表中删除"arena_api @ file://localhost/%s" % wheel_path这一行。 - 确保Wheel被打包进分发包:在项目根目录创建
MANIFEST.in文件,添加内容:include hardware_tools/support/arena_api-2.3.3-py3-none-any.whl - 添加自定义Post-Install命令:在setup.py中插入以下类定义,替换原有
cmdclass配置:
然后修改class PostInstallCommand(Command): """Post-installation command to install local arena_api wheel""" description = 'Install bundled arena_api wheel' user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): import subprocess import sys # 获取安装后Wheel在site-packages中的路径 wheel_target = os.path.join(self.install_lib, 'hardware_tools', 'support', 'arena_api-2.3.3-py3-none-any.whl') subprocess.check_call([sys.executable, '-m', 'pip', 'install', wheel_target])setup()中的cmdclass:cmdclass={ "install": PostInstallCommand, # 若UploadCommand未定义,直接删除该行 # "upload": UploadCommand, },
方案2:用package_data替代data_files优化文件打包
data_files是系统级路径配置,跨环境易出问题,改用包级别的package_data更可靠:
- 删除setup.py中的
data_files配置,替换为:package_data={ 'hardware_tools.support': ['arena_api-2.3.3-py3-none-any.whl', 'config.json', 'aardvark.dll'], }, - 配合方案1中的Post-Install脚本,即可完成私有Wheel的自动安装。
方案3:直接打包成Wheel格式分发
如果目标环境支持Wheel包,可跳过sdist直接生成Wheel文件:
- 先安装wheel工具:
pip install wheel - 执行打包命令:
python setup.py bdist_wheel - 将生成的
.whl文件分发到目标环境,配合Post-Install脚本完成私有Wheel安装。
内容的提问来源于stack exchange,提问作者ekorb
相关产品推荐
相关产品推荐

