什麼是 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絕對不只這點玩法,這裏我寫的就是簡單入了個門,希望在自己學會知識的同時能夠對其他感興趣的人有一定的幫助。