python打包

<!DOCTYPE html>


python打包




css

python打包


python打包有一個組織叫python packaging authority(pypa).還有一個python第三方倉庫叫Python Package Index(Pypi)
與包有關的兩種工具,一種是安裝包的工具,另外一種工具用於包的建立和分發
html


安裝包的工具



  1. pip安裝來自PyPI的包

  2. virtualenv或venv用於python環境的應用隔離


包的建立與分發



  1. 使用setuptools來定義項目並建立源代碼發行版

  2. 使用wheel來建立構建發行版

  3. 使用twine像PyPI上傳包


打包上傳須要的操做工具



  • 使用setuptools來建立項目源代碼發行商

  • 使用wheel進行構建發行版,也就是打包

  • 使用twine像pypi倉庫上傳包的發行版


項目配置


建立大型的應用最簡單的作法是分幾個包,這樣就像分紅各個組件,這樣易於理解維護和修改。
python

  1. setup.py

    一個須要上傳入pypi的包來講,其應用根目錄須要包含一個setup.py腳本。setup文件要包含能夠被distutils打包工具能夠解析的全部數據,使用setup()函數來傳入元數據。distutils是一個標準模塊,建議使用setuptools包來替換distutils,由於setuptools作了一些改進

    setup文件的最少內容狀況


    from setuptools import setup 

    setup(

    name='wjtestpack'

    )

setup中name的參數爲要打包的全名,setup腳本可使用一些命令,使用以下命令查看 git

python3 setup.py --help-commands  
#輸出結果
Standard commands:#標準命令 是distutils的內置命令
build build everything needed to install
build_py "build" pure Python modules (copy to build directory)
build_ext build C/C++ extensions (compile/link to build directory)
build_clib build C/C++ libraries used by Python extensions
build_scripts "build" scripts (copy and fixup #! line)
clean clean up temporary files from 'build' command
install install everything from build directory
install_lib install all Python modules (extensions and pure Python)
install_headers install C/C++ header files
install_scripts install scripts (Python or otherwise)
install_data install data files
sdist create a source distribution (tarball, zip file, etc.)
register register the distribution with the Python package index
bdist create a built (binary) distribution
bdist_dumb create a "dumb" built distribution
bdist_rpm create an RPM distribution
bdist_wininst create an executable installer for MS Windows
check perform some checks on the package
upload upload binary package to PyPI

Extra commands:setuptools包中定義的命令
bdist_wheel create a wheel distribution
alias define a shortcut to invoke one or more commands
bdist_egg create an "egg" distribution
develop install package in 'development mode'
easy_install Find/get/install Python packages
egg_info create a distribution's .egg-info directory
install_egg_info Install an .egg-info directory for the package
rotate delete older distributions, keeping N newest files
saveopts save supplied options to setup.cfg or other config file
setopt set an option in setup.cfg or another config file
test run unit tests after in-place build
upload_docs Upload documentation to PyPI

usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
or: setup.py --help [cmd1 cmd2 ...]
or: setup.py --help-commands
or: setup.py cmd --help

setup.cfg

setup.cfg文件就是包含setup腳本命令的默認參數數據。若是建立包的過程複雜,須要像setup腳本傳入參數不少,使用這個文件就簡單不少。能夠講項目的默認參數保存在這個文件中。也將包的構建過程透明化。
cfg文件與configparser語法相同,都是一個個節點與值對應 程序員

[global]
quiet=1
[sdist]
formats=zip,tar
[bdist_wheel]
universal=1

以上配置描述的是,發行包建立格式爲zip和tar兩種格式的文件,而且構建wheel打包,全局命令quiet爲1,因此命令的大部分輸出被阻止。 github

manifest.in

mainifest文件就是一個包含發行包的全部文件的信息的文件,使用sdist命令構建包的時候,distutils會自動瀏覽應用中的全部文件,生成列表,保存在manifest文件中 web

打包須要的元數據

除了須要的包名和版本以外,setup函數能夠接受不少參數
* description:描述包的信息 * longdescription:完整包的說明,可使用reStructuredText格式
* keywords:包中關鍵字列表
* author:做者的名稱
* author
email:做者郵箱
* url:項目URL * license:許可證
* packages:包中全部名稱的列表,setuptools有一個findpackages的函數計算
* namespace
packages:命令空間包的列表 編程

分發器trove

分類器的主要做用是對你建立的包在pypi中有一個所屬類的定位,分類器都是字符串形式,用::字符串分割每一個命名空間。分類器列表在包的setup()函數中定義用的參數爲classifiers,舉個例子 canvas

from setuptools import setup
setup(
name='mytestpack'
classifiers=[
'Development Status:: 4-Beta',
'Intended Audience::Developers',
'License::OSI...',
'Operating System::OS',....
] )

pypi分類器一共有9大類
* 開發狀態(Development Status) * 環境(Environment) * 框架(Framework) * 目標受衆(Intended Audience) * 許可證(License) * 天然語言(Natural Language) * 操做系統(Operating System) * 編程語言(Programming Language) * 話題(Topic) windows

常見模式

其實打包信息能夠在setup函數中接受大多數元數據的手動輸入,代碼以下

from setuptools import setup
setup(
name='mytestpack'
version='0.0.1',
description='test package',
long_description='wj first use setuptools',
install_requires=[
'dependency1',
'dependenct2',
]
)

可是setuptools和distutils都不能從項目源代碼中自動提取元數據信息,須要你本身提供這些信息。長遠來看上面的方法很難維護。因此python社區有一些方法來解決這些問題:
(1) 自動添加包的版本字符串
這個操做須要將包的版本信息編寫進包的init.py文件中,因此之後建立包的init.py文件須要包含以下格式的信息

VERSION=(0,1,1)
__version__='.'.join([str(x) for x in VERSION])

版本信息包含在VERSION和version中,這樣訪問這兩個變量就能夠獲取版本號,因此在setup.py腳本中動態獲取版本號代碼以下

from setuptools import setup  
import os
def get_version(version_tuple):
if not isinstance(version_tuple[-1],int):
return '.'.join(map(str,version_tuple[:-1]))+version_tuple[-1]
return '.'.join(map(str,version_tuple))
init=os.path.join(os.path.dirname(__file__),'下一層文件夾命',...,'__init__.py')
version_line=list(
filter(lambda l:l.startswith("VERSION"),open(init))
)[0]
VERSION=get_version(eval(version_line.split('=')[-1]))
setup(
name='mytestpack',
version=VERSION,
)

(2)使用README文件
python包在pypi中會顯示一個項目的readme文件,pypi只支持reStructuredText標記語言。固然若是想使用其餘語言,那就只能讀取文件,而後將數據賦值到long_description中,這樣也能夠顯示。這時須要使用pypandoc包將其餘語言轉換爲reStructuredText

try:  
from pypandoc import convert
def read_md(f):
return convert(f,'rst')
except ImportError:
covert=None
print('warning:pypandoc not found')
README=os.path.join(os.path.dirname(__file__),'README.md')
setup(
name='mytestpack',
long_description=read_md(README),
)

(3)管理依賴
有些應用包的須要依賴其餘包,這就要咱們列出一個依賴列表,以下是一個明確表述依賴列表的形式:

from setuptools import setup
setup(
name='mytestpack',
install_requires=['pack1','pack2','pack3'],
)

也可使用讀取requirements.txt文件的形式

from setuptools import setup  
import os
def strip_comments(l):
reeturn l.split('#',1)[0].strip()
def reqs(*f):
return list(filter(None,[strip_comments(l) for l in open(os.path.join(os.getcwd(),*f)).readlines()]))
setup(
name='mytestpack',
install_requires=reqs('requirements.txt')
)

自定義包命令

distutils提供了自定義命令的入口點(entry point),只要在setup函數裏使用entry_point參數就能夠註冊命令,這樣的形式和crf文件格式相似

setup(
name='mytestpack',
entry_point="""
[distutils.commands]
my_command=my.command.module.Class
""",
)

開發期間使用包

開發期間使用包就是爲了測試包是否能正藏安裝
1.安裝
使用pip命令就能夠將安裝包註冊到python樹中,由於個人電腦裏有兩個版本的python,因此python的pip命令以下

python3 -m pip install C:\Users\Mr.Bool\Desktop\testproject\testp

2.卸載

python3 -m pip uninstall C:\Users\Mr.Bool\Desktop\testproject\testp

在系統包上卸載包是很危險的可能會卸掉某些重要文件,這也證實虛擬環境對於開發的重要性 3.開發模式下安裝

python3 -m pip install -e C:\Users\Mr.Bool\Desktop\testproject\testp

命名空間包

命名空間有兩種,一種是上下問的命名空間,即保存變量的字典稱爲命名空間,有模塊的全局命名空間,函數方法的本地命名空間,內置名稱的命名空間
1. 內置命名空間在 Python 解釋器啓動時建立,會一直保留,不被刪除。
2. 模塊的全局命名空間在模塊定義被讀入時建立,一般模塊命名空間也會一直保存到解釋器退出。
3. 當函數被調用時建立一個局部命名空間,當函數返回結果 或 拋出異常時,被刪除。每個遞歸調用的函數都擁有本身的命名空間。
還有另一種命名空間,叫作命名空間包,這是在項目中對於打包的時候用的一種功能。

做用

當你在開發應用是一般是多個組件,舉個例子是當你的一個大的應用a中,包含b,c兩個模塊,而b和c是單獨存在的兩個模塊,你能夠單獨使用,在沒有命名空間包的狀況下這是不可能的狀況,由於b和c都在a的下面,要下載就只能都下載,出現了命名空間包,那麼將a變成命名空間包,那麼就在python的層面上將b,c能夠單獨使用和修改。但兩個包又能夠同時存在a的下面。

pip install a.b
pip install a.c

而沒有命名空間包的時候你要下載通用包

pip install a

使用

隱式命名空間包

隱式命名空間包意思就是隻要在你寫的應用中,不包含init.py的包就做爲命名空間包,setup.py腳本中這樣寫:

from setuptools import setup
setup(
name='a.b',
packages=['a.b'],
)

古老的命名空間包

古老的方法在a中是有文件init.py文件的,但必須是空白,但最好添加一段代碼

__import__('pkg_resources').declare_namespace(__name__)

在setup文件中這樣聲明

from setuptools import setup
setup(
name='a.b',
packages=['a.b],
namespace_packages=['a'],#主動聲明命名空間包
)

上傳一個包

python包倉庫

從pypi上下載python包不須要帳號,只須要一個包管理器。首選是pip

上傳到pypi或其餘倉庫

任何人均可以上傳python包,只須要註冊倉庫的帳戶密碼,包與帳戶綁定。上傳一個包的簡單方法使用setup.py的命令upload

python setup.py 命令列表 upload  

若是你想同事構建源代碼發行版、構建發行版和wheel包,使用以下命令

python setup.py sdist bdist bdist_wheel upload

由於這樣做不安全,最好使用twine工具,能夠在pypi平臺下載,

pytho setup.py sdist bdist_wheel  
twine upload dist/*

若是這個包沒有註冊上傳會失敗,先註冊

python register dist/*

.pypirc

.pypirc是一個配置文件,保存python包倉庫的信息

[distutils]
index-servers=pypi other #註冊的倉庫
[pypi]
repository:<倉庫url>
username:用戶名
password:密碼
[other]
repository:<倉庫url>
username:用戶名
password:密碼

用戶名密碼能夠空着,安全,必要時程序會提示輸入

源代碼包與構建包

1.sdist
sdist命令建立源代碼發行版

python setup.py sdist

生成的文件形式爲舉例:mypackage-0.1.1.tar.gz的打包文件包含與項目相同的結構
2.bdist和wheels
分發預構建的發行版

python setup.py bdist

會生成文件形式爲wjtestpack-0.0.0.win-amd64.zip格式的壓縮包,這個包裏主要有site-packages的文件夾,和一些緩存字節碼.pyc結尾的文件。
使用wheels命令以下

python setup.py bdist_wheel

生成的文件爲wjtestpack-0.0.0-py3-none-any.whl形式的文件。

獨立可執行文件

建立獨立可執行文件是每種語言必須實現的,由於不會全部使用者都是程序員,也不會全部使用應用的電腦都有特定語言的解釋環境。

可執行文件的編譯工具

PyInstaller(首選工具)

能夠應用到多平臺,不支持跨平臺構建,使用pyinstaller首先須要用pip安裝pyinstaller,使用pyinstaller建立獨立可執行文件的命令以下

pyinstaller 路徑/mytest.py

這樣運行會生成一個.spec文件和一個dist文件夾,文件夾中包含,許多文件,其中有一個exe可執行文件,當將應用發給用戶時必須將整個文件夾發給用戶。也可使用以下命令

pyinstaller --onefile mytest.py

使用--onefile構建能夠去掉全部多餘文件,在一會有.spec文件和dist文件夾下一個.exe可執行文件。
.spec是一個配置文件,其實使用配置文件也能夠生成可執行文件,命令以下,前提必須現有.spec文件,能夠本身編寫

pyinstaller mytest.spec

cx_Freeze

也是可應用到多平臺,不支持跨平臺構建,這個工具的缺點爲不能只生成可執行文件,它必須生成多個dll等關聯文件。生成可執行文件命令爲

cxfreeze mytest.py

cxfreeze擴展了distutils包,能夠直接使用setup.py文件配置構建生成可執行文件,setup.py代碼以下

import sys  
from cx_Freeze import setup,Executable
setup(
name='mytest',
version='0.0.1',
description='使用cxfreeze',
options={
'build_exe':build_exe_options
},
executables=[Executable('mytest.py')]
)

執行命令爲

python setup.py build_exe  

py2exe和py2app

py2exe爲生成windows程序的工具,py2app爲生成mac程序的工具,兩個工具優先級比前兩個低,若是前兩個很差用,再用這兩個

相關文章
相關標籤/搜索