setuptools製作whl包實戰講解(一)

什麼是 whl

.whl格式的文件本質上是一個壓縮包,裏面包含了py文件,以及經過編譯的pyd文件。使得可以在不具備編譯環境的情況下,選擇合適自己的python環境進行安裝。我們可以使用我們非常熟悉的pip install 來安裝whl包。
如:

pip install mask_detect_v1.0.whl

如何製作whl包

setuptools

Setuptools是Python Distutils的加強版,使開發者構建和發佈Python包更加容易,特別是當包依賴於其他包時。用setuptools構建和發佈的包與用Distutils發佈的包是類似的。包的使用者無需安裝setuptools就可以使用該包。
文檔:
setuptools
文檔裏的說明還是比較清楚的,本篇文章就以最近做的一個口罩識別項目爲例做一個demo,方便自己也方便讀者快速你的打whl包。
項目:
Mask-detection-system
目錄樹
查看項目的工程結構,我們想將所有的python文件和cfg文件夾、weights文件夾,以及一些需要用到的數據如voice文件夾下的wav文件都一併打包到whl包中。
照貓畫虎似的,我可以寫出這樣的setup.py

from setuptools import setup, find_packages

setup(
    name='mask-detection-system-1',
    version='dev_v1.0',
    description='mask detection',
    keywords='mask',
    packages=find_packages(),
    install_requires=[
        'numpy',
        'opencv-python-headless',
        'torch',
        'matplotlib',
        'pycocotools',
        'tqdm',
        'pillow',
        'pydub',
        'pyttsx3'
    ],
        author='CreateLAB',
)

這裏需要解釋的一個setuptools中的函數就是find_packages(),find_packages()簡單的說就是能夠查找setup.py所在的根目錄下所有的python包。那麼什麼是python包呢?
包含有__init__.py的文件夾就被稱爲python包。
使用find_packages()函數能夠將根目錄下所有的python包都打包起來。這樣我就分別在根目錄、project文件夾、voice文件夾下都放入了__int__.py,這樣我預想就能夠實現將所有python文件和音頻數據都打包起來的預想。但事實並不是這樣。我們可以來看打包後的效果。

python setup.py sdist bdist_wheel

打包好的whl包會出現在dist文件夾中個,我們將其提取,看看裏面到底打包了什麼?
打包的結果很明顯,這與我想要的打包效果不符,主要有以下幾個問題:

  • 根目錄下的py文件都沒有被打包
  • voice文件夾下的音頻文件沒有被打包
  • 目前只有python文件,那麼cfg和weights都沒打包進來
    由此可見 find_packages()只能打包python包,python包中只有.py而不包括這個文件夾下 其他的數據文件。並且根目錄下的.py文件不會被打包進去。

如何打包數據文件

這裏就不得不提到setuptools中 include_package_data、 package_data

  • include_package_data:當指定include_package_data=True時,setuptools會自動提取所有包中所有的指定格式的數據文件,數據文件必須通過MANIFEST.in文件中進行指定。
  • package_data:package_data是一個字典,可以指定想要的數據文件。
    MANIFEST.in的寫法:MANIFEST
    我們將include_package_data設爲True,並且編寫MANIFEST.in
recursive-include ./voice *.wav
recursive-include ./cfg *.cfg
recursive-include ./weights *.pt

將MANIFEST.in放進根目錄,再進行打包。奇蹟發生了!!!
加入數據文件我們想要的數據文件就這樣輕鬆的被打包進去啦!!!
那麼我就在像,這樣我們還要package_data幹個錘子?我理解這就是兩種方法,我們現將MANIFEST.in刪除掉。嘗試使用package_data來打包數據文件。

from setuptools import setup, find_packages

setup(
    name='mask-detection-system-1',
    version='dev_v1.0',
    description='mask detection',
    keywords='mask',
    packages=find_packages(),
    include_package_data=True,
    package_data={
        # 由於voice是一個包,因此無需指定包名
        "": ["./*.wav"],
        # 而cfg並不是一個包,因此需要指定cfg包名
        "cfg": ["./*.cfg"],
    },
    install_requires=[
        'numpy',
        'opencv-python-headless',
        'torch',
        'matplotlib',
        'pycocotools',
        'tqdm',
        'pillow',
        'pydub',
        'pyttsx3'
    ],
        author='CreateLAB',
)

這樣也能夠將數據文件進行打包,看過公司工程院大佬寫的setup.py,大多數都使用的這種方法,因此我個人認爲這種方法更爲推薦。

如何打包根目錄下的python文件

如果根目錄下有python文件怎麼辦呢?
這就需要介紹scripts參數了,scripts能夠指定獨立存在的文件,也就是不在包裏。
現在我們將setup.py改寫成如下

from setuptools import setup, find_packages

setup(
    name='mask-detection-system-1',
    version='dev_v1.0',
    description='mask detection',
    keywords='mask',
    packages=find_packages(),
    include_package_data=True,
    package_data={
        # 由於voice是一個包,因此無需指定包名
        "": ["./*.wav"],
        # 而cfg並不是一個包,因此需要指定cfg包名
        "cfg": ["./*.cfg"],
    },
    scripts=["./detect.py",
             "./models.py",
             "./test.py",
             "./train.py",
             ],
    install_requires=[
        'numpy',
        'opencv-python-headless',
        'torch',
        'matplotlib',
        'pycocotools',
        'tqdm',
        'pillow',
        'pydub',
        'pyttsx3'
    ],
        author='CreateLAB',
)

這回舒服了!已經將項目打包成了我想要的形式。
最終結果當然了,setuptools絕對不只這點玩法,這裏我寫的就是簡單入了個門,希望在自己學會知識的同時能夠對其他感興趣的人有一定的幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章