首頁  >  文章  >  後端開發  >  打包發布Python模組的方法詳解

打包發布Python模組的方法詳解

高洛峰
高洛峰原創
2017-02-22 17:03:171668瀏覽

前言

昨天把自己的VASP檔案處理庫進行了打包並上傳到PyPI,現在可以直接透過pip和easy_install來安裝VASPy啦(同時歡迎使用VASP做計算化學的童鞋們加星並參與其中),

VASPy的GotHub網址:https://github.com/PytLab/VASPy
VASPy的PyPI網址:https://pypi.python.org/pypi/vaspy/

由於自己的記性真是不咋地,怕時間久了就忘了,於是在這裡趁熱打鐵以自己的VASPy程序為例對python的打包和上傳進行下總結。

VASPy套件檔案結構

先寫貼上來VASPy套件的整個檔案結構, 後面的內容都是以此為例進行說明:

VASPy/
├── LICENSE
├── MANIFEST
├── MANIFEST.in
├── README.rst
├── requirements.txt
├── scripts
│  ├── change_incar_parameters.py
│  ├── create_inputs.py
│  └── ...
├── setup.cfg
├── setup.py
├── tests
│  ├── incar_test.py
│  ├── __init__.py
│  ├── oszicar_test.py
│  ├── outcar_test.py
│  ├── testdata
│  │  ├── CONTCAR
│  │  ├── DOS_SUM
│  │  ├── ELFCAR
│  │  └── ...
│  └── ...
└── vaspy
  ├── __init__.py
  ├── iter.py
  ├── matstudio.py
  └── ...
  
4 directories, 54 files

打包和安裝第三方包的工具

這裡我們需要藉助setuptools和pip等工具進行自己包的打包和發布以及安裝,如果需要構建成wheel還需要安裝wheel模組。如果python版本>=2.7.9或>=3.4,setuptools和pip是已經安裝好的,可能需要更新到最新版本

pip install -U pip setuptools

可以使用套件管理工具,例如

yum install pip
sudo apt-get install pip

透過get-pip.py腳本安裝,如果偵測到沒有安裝wheel和setuptools也會自動安裝

python get-pip.py

具體的工具安裝與介紹就不多講了,可以請參考requirements for installing packages

#套件中不同檔案的作用

##setup.py

這個文件是打包整個專案最重要的文件,它裡面提供了兩個主要的功能:

setup()函數,此函數的參數指定如何配置自己的專案。

命令列工具,包括打包,測試,發布等。可以透過下面的命令查看;

python setup.py --help-commands

setup.cfg

此檔案包含了建置時候的一些預設參數例如建置bdist_wheel的時候的--universal參數

[bdist_wheel]
universal=1

這樣每次打包的時候就會預設使用--universal參數了,效果類似:

python setup.py bdist_wheel --universal


README.rst

這個最初我是用markdown寫的,打包發佈到PyPI之後發現PyPI不支援markdown的渲染,頁面上真是一片混亂,於是就用​​reStrutruedText的語法重新寫了一遍。畢竟標記語言語法基本上可以秒上手,實在不行找個模板比葫蘆畫瓢就行。

reStructureText的語法規則可參考官方文件:Quick reStructuredText

其實還有一種方法就是使用pandoc將markdown轉換成rst格式,一種省事的方式就是使用pyandoc模組在發布的時候自動轉換。

具體方法可以參考:Use Markdown README's in Python modules

MANIFEST.in

此文件在打包的時候告訴setuptools還需要額外打包那些文件,例如我VASPy中的單元測試的測試數據文件我就使用這個文件將其包含進來。當然README,LICENSE這些也可以透過它來一起打包進來。

以下是我自己的MANIFEST.in的內容:

include README.rst
include requirements.txt
include LICENSE
recursive-include scripts *
recursive-include tests *

具體的語法規則可以參考:The MANIFEST.in template

vaspy/

#此資料夾就是vaspy原始碼所在的套件。

tests/

此資料夾也是一個子包,包含了單元測試腳本,為了能使用python setup.py test進行單元測試,特地添加了__init__.pys使其成為一個包。

setup()的參數

這裡只介紹我使用的幾個參數,其他參數的具體使用可以參考:https://docs.python.org/3/distutils/setupscript .html

name

versions = "vaspy"


#是整個專案的名字,打包後會使用此名稱和版本號。

version

from vaspy import __version__
version = __version__

description

是一個簡短的對項目的描述,一般一句話就好,會顯示在pypi上名字下端。

long_description

是一個長的描述,相當於對專案的一個簡潔,如果此字串是rst格式的,PyPI會自動渲染成HTML顯示。這裡可以直接讀取README.rst中的內容。

url

套件的連接,通常是GitHub上的連結或readthedocs的連結。

packages

需要包含的子包列表,setuptools提供了find_packages()幫助我們在根路徑下尋找包,這個函數distutil是沒有的。

setup_requires

這個參數定義了VASPy安裝和順利執行所需的其他依賴項(最基本的),使用pip安裝的時候會對這些依賴項進行安裝。

關於這個參數與requirements.txt的差異可以參考:install_requires vs Requirements files

classifier

這個參數提供了一系列的分類,在PyPI上會將其放入不同的目錄中講項目進行歸類。

具體的categories的名稱和規則參考:https://pypi.python.org/pypi?%3Aaction=list_classifiers

test_suite

這個參數可以幫助我們使用

python setup.py test


來跑單元測試,再也不需要單獨再寫一個腳本例如run_tests.py這樣來跑單元測試了。

此參數的官方解釋:

A string naming a unittest.TestCase subclass (or a package or module containing one or more of them, or a method of such a subclass), or naming a function that can be called with no arguments and returns a unittest.TestSuite. If the named suite is a module, and the module has an additional_tests() function, it is called and the results are added to the tests to be run. If the named suite is a package, any submodules and subpackages are recursively added to the overall test suite.

也就是说这个参数可以接受多种类型的参数:

接收unittest.TestCase子类,我们可以讲所有单元测试写入一个测试用例中,然后import进来,再传你给test_suite
接收函数对象,此函数对象没有任何参数,且返回一个unittest.TestSuite.这样我们就可以单独写一个函数,将多个测试用例合并成一个suite然后返回,然后再将函数import进来传给test_suite。

模块和包名称,我就是使用这种方式,之前自己的测试都是分开的多个脚本,这样我添加一个__init__.py就可以将其变成一个包,将包名传给test_suite,setuptools就会神奇的将此包下的所有测试全部跑一边,这样我以后再加测试脚本的时候直接就添加新的脚本就好了,其他的都不需要改动了。

运行效果:

zjshao@SHAO-PC:/mnt/d/Dropbox/Code/CentOS_code/VASPy$ python setup.py test
running test
running egg_info
creating vaspy.egg-info
writing vaspy.egg-info/PKG-INFO
writing top-level names to vaspy.egg-info/top_level.txt
writing dependency_links to vaspy.egg-info/dependency_links.txt
writing manifest file 'vaspy.egg-info/SOURCES.txt'
reading manifest file 'vaspy.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'vaspy.egg-info/SOURCES.txt'
running build_ext
test_compare (tests.incar_test.InCarTest)
Make sure we can compare two InCar objects correctly. ... ok
test_eq (tests.incar_test.InCarTest)
Test __eq__() function. ... ok
...
此处省略若干输出
  
----------------------------------------------------------------------
Ran 22 tests in 3.574s
  
OK

发布自己的python包

1. 首先先去PyPI注册帐号

2. 配置~/.pypirc如下:

[distutils]
index-servers =
  pypi
  pypitest
  
[pypi]
username:ShaoZhengjiang
password:mypassword
  
[pypitest]
username:ShaoZhengjiang
password:mypassword

3. 然后注册并上传自己的包到测试服务器

pypi提供了一个测试服务器,我们可以在这个测试服务器上做测试。

python setup.py register -r pypitest

然后

python setup.py sdist upload -r pypitest

若没有问题我们应该不会得到任何错误。

4. 上传至PyPI

若上面的测试成功,我们就可以按照相同的步骤将包注册并上传。

python setup.py register -r pypi
python setup.py sdist upload -r pypi

Ok,之后我们就可以在PyPI(https://pypi.python.org/pypi/vaspy/)上看到我们自己的包了。

更多打包发布Python模块的方法详解相关文章请关注PHP中文网!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn