Python 打包成 wheel

1. 编写 setup.py

在项目的根目录下外面一个文件夹创建 setup.py

name:指的是你打包后发布的名称(如numpy和torch)

version:版本号。

packages:需要处理的包目录(通常为包含 __init__.py 的文件夹)。

find_packages:用于添加大量包的情况,exclude为排除的包,include为包含的包(网上大多都是这样写的,但是不知道是否需要加后缀什么的)。

package_dir:指定哪些目录下的文件被映射到哪个源码包。

ext_modules:指定扩展模块。

install_requires:需要安装的依赖。(如果没有代理下得太慢,不如写 requirements.txt 然后用国内镜像安装)

from setuptools import find_packages, setup, Extension, Command
setup(name='center_net_obj_det',
      # 表示 CenterNet 文件夹中的都打包
      packages=[p for p in find_packages() if p.startswith('CenterNet')],   
      version='0.0.4'
      # ext_modules=[Extension('object_detection_tutorial', ['object_detection_tutorial.c'])],
      # install_requires=[
      #     'torch==0.4.1',
      #     'opencv-python',
      #     'Cython',
      #     'numba',
      #     'progress',
      #     'matplotlib',
      #     'easydict',
      #     'scipy',
      #     'numpy'
      # ]
      )

1.1. 示例

  • setup.py
#!/usr/bin/env python3

PROJ_NAME = 'you-get'
PACKAGE_NAME = 'you_get'
PROJ_METADATA = '%s.json' % PROJ_NAME
VERSION = '0.4.1651'

import os, json
here = os.path.abspath(os.path.dirname(__file__))
proj_info = json.loads(open(os.path.join(here, PROJ_METADATA), encoding='utf-8').read())
try:
    README = open(os.path.join(here, 'README.rst'), encoding='utf-8').read()
except:
    README = ""

from setuptools import setup, find_packages
setup(
    name = proj_info['name'],
    version = VERSION,
    author = proj_info['author'],
    author_email = proj_info['author_email'],
    url = proj_info['url'],
    license = proj_info['license'],
    description = proj_info['description'],
    keywords = proj_info['keywords'],
    long_description = README,
    packages = find_packages('src'),
    package_dir = {'' : 'src'},
    test_suite = 'tests',
    platforms = 'any',
    zip_safe = True,
    include_package_data = True,
    classifiers = proj_info['classifiers'],
    entry_points = {'console_scripts': proj_info['console_scripts']},
    extras_require={
        'socks': ['PySocks'],
    }
)
{
  "name": "you-get",
  "author": "Mort Yao",
  "author_email": "mort.yao@gmail.com",
  "url": "https://you-get.org/",
  "license": "MIT",
  "description": "Dumb downloader that scrapes the web",
  "keywords": "video download youtube youku niconico",
  "classifiers": [
    "Development Status :: 4 - Beta",
    "Environment :: Console",
    "Intended Audience :: Developers",
    "Intended Audience :: End Users/Desktop",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3 :: Only",
    "Programming Language :: Python :: 3.7",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Topic :: Internet",
    "Topic :: Internet :: WWW/HTTP",
    "Topic :: Multimedia",
    "Topic :: Multimedia :: Graphics",
    "Topic :: Multimedia :: Sound/Audio",
    "Topic :: Multimedia :: Video",
    "Topic :: Utilities"
  ],
  "console_scripts": [
    "you-get = you_get.__main__:main"
  ]
}

2. 生成 .whl 文件

先安装 wheel:pip install wheel

直接使用如下命令

python setup.py bdist_wheel

即可在当前目录生成一个 dist 文件夹,一个 build 文件夹和一个 xxxx.egg-info 文件。

3. 安装发布

进入文件夹 dist,里面也有一个 xxx.whl 文件,输入命令 pip install xxx.whl 即可安装。如果有已安装的版本,输入 pip install xxx.whl --force 即可重新安装。

安装后通过文件的组织结构来调用库,如某项目的文件架构如下

CenterNet
|-src
    |-object_detection_tutorial.py
    |-...
|-...

如果想要调用object_detection_tutorial.py的ObjectDetection类,需要如下导入

from CenterNet.src.object_detection_tutorial import ObjectDetection

4. Bug

4.1. nms.so

报错信息为

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/cuicui/CenterNet/src/object_detection_tutorial.py", line 16, in <module>
    from detectors.detector_factory import detector_factory
  File "/home/cuicui/CenterNet/src/lib/detectors/detector_factory.py", line 5, in <module>
    from .exdet import ExdetDetector
  File "/home/cuicui/CenterNet/src/lib/detectors/exdet.py", line 15, in <module>
    from external.nms import soft_nms
ImportError: /home/cuicui/CenterNet/src/lib/external/nms.so: undefined symbol: _Py_ZeroStruct

解决方法为进入对应文件夹重新编译并安装,如下

$ cd /home/cuicui/CenterNet/src/lib/external/
$ sudo make
$ python setup.py build_ext install

4.2. so 文件无法 import

python 打包后 .so 文件无法 import,见问题第四条

4.3. 引用库路径问题

项目中如果把项目根目录作为 Sources Root,进行路径引用库会报错(使用相对路径不会报错),可以将需要 import 的路径加入系统路径,如下

import os
import sys

this_dir = os.path.dirname(__file__)    # 可根据该地址进行相对路径的更改
sys.path.insert(0, this_dir)

import xxx      # 这样就可以引用 this_dir 文件夹下的库了

发表评论

邮箱地址不会被公开。 必填项已用*标注