You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将本地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

  1. 移除install_requires中的本地Wheel引用:从REQUIRED列表中删除"arena_api @ file://localhost/%s" % wheel_path这一行。
  2. 确保Wheel被打包进分发包:在项目根目录创建MANIFEST.in文件,添加内容:
    include hardware_tools/support/arena_api-2.3.3-py3-none-any.whl
    
  3. 添加自定义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更可靠:

  1. 删除setup.py中的data_files配置,替换为:
    package_data={
        'hardware_tools.support': ['arena_api-2.3.3-py3-none-any.whl', 'config.json', 'aardvark.dll'],
    },
    
  2. 配合方案1中的Post-Install脚本,即可完成私有Wheel的自动安装。

方案3:直接打包成Wheel格式分发

如果目标环境支持Wheel包,可跳过sdist直接生成Wheel文件:

  1. 先安装wheel工具:pip install wheel
  2. 执行打包命令:python setup.py bdist_wheel
  3. 将生成的.whl文件分发到目标环境,配合Post-Install脚本完成私有Wheel安装。

内容的提问来源于stack exchange,提问作者ekorb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:44:51