先々週くらいに仕事で pip パッケージを作った。いろいろと忘れていたので苦労した。
その時にioproveを作ったときのメモが役にたったので少し書き換えて晒しておく。
(いい加減、Dropbox, Evernote, Boostnoteとかに散らばったメモを統一したい)
ここでは pip パッケージを作って登録するまでの手順を記録する。
ioproveは書き捨てコードだけど、使いみちがあったので少し直してPyPIに登録した。
実際のPyPIへの登録の時にはtwineは使わなかったのだけど、メモを書く時に調べていたら見つけ良さそうだったためここでは使うように書いている。
ref.
パッケージのディレクトリ構造について
ディレクトリ構造は以下のようになっている。前にmodern-package-templateを使って生成したこともあって他にもファイルが生成されてたけど、だいたいこんな感じ。
1
2
3
4
5
6
7
8
9
10
11
12
|
$ tree
.
|-- NEWS.txt
|-- README.rst
|-- requirements.txt
|-- setup.py
|-- src
| `-- ioprobe
| |-- __init__.py
| |-- helper.py
| `-- test_ioprobe.py
`-- tox.ini
|
ファイル |
意味 |
src |
ソースルート |
tox.ini |
tox(テストランナー)の設定 |
setup.py |
パッケージのメタ情報 |
NEWS.txt, README.rst |
setup.py から読み込んでるドキュメント |
requirements.txt |
pip で依存パッケージを読み込むために使う(setup.py あるし今はもう要らない) |
setup.pyを書く
Pythonスクリプトでsetuptoolsをインポートして使う。
基本的に setup() 関数にメタ情報を渡せば終わり。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
from setuptools import setup, find_packages
import os
here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README.rst')).read()
NEWS = open(os.path.join(here, 'NEWS.txt')).read()
version = '0.1.1'
install_requires = []
setup(name='ioprobe',
version=version,
description="Observation tool for I/O per process",
long_description=README + '\n\n' + NEWS,
classifiers=[
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: Implementation :: CPython',
'Topic :: Software Development :: Libraries',
'Environment :: Console',
'Topic :: Utilities',
],
keywords='proc system process io',
author='Masumi Kanai',
author_email='masumi.net@gmail.com',
url='https://github.com/masu-mi/ioprobe',
license='The BSD 3-Clause License',
packages=find_packages('src'),
package_dir={'': 'src'}, include_package_data=True,
zip_safe=False,
install_requires=install_requires,
extras_require = {
'test': [
'pytest', 'tox',
'mock;python_version<"3.3.0"'
],
},
entry_points={
'console_scripts': ['ioprobe=ioprobe:main']
})
|
classifiers
パッケージの分類タグをリストで渡す。(ref classifiers一覧)
install_requires
依存パッケージをリストで渡す。(<,>,==,<=,>=,!= などでバージョン指定が可能)
他に、provide,obsoletes
インストール条件を設定する
install_requires,extras_require ではインストールする条件を、 ; で区切った後に条件を記述できる。
'package_name;platform_system=="Windows"',
'package_name;python_version<"3.3.0"'
条件ごとの依存パッケージをリストで渡す。
環境は setup.py のあるディレクトリで pip を使う際に下のようにサブコマンドの後ろで .[${env_name}] と指定する。
1
|
$ sudo pip install .[test]
|
entry_points
キーは console_scripts,gui_scripts が代表的で $script_name=${package_name}:${func_name}
という形式の文字列のリストを値としたマップが格納される。
PyPIにアップロードする
PyPIへのアップロードの方法を書く。twineと setup.py それぞれでアップロードしてみる。
その際に認証情報などを ~/.pypirc に設定する。
[distutils]
index-servers =
pypi
pypitest
[pypi]
username=USER
password=PASSWORD
[pypitest]
repository=https://test.pypi.org/legacy/
username=USER
password=PASSWORD
事前にビルドする。
1
|
$ python setup.py sdist bdist_wheel
|
setup.pyを使ってアップロードする
普通は setup.py でアップロードする。アップロードする。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
$ python setup.py upload -r pypitest
running sdist
running egg_info
writing requirements to src/ioprobe.egg-info/requires.txt
writing src/ioprobe.egg-info/PKG-INFO
writing top-level names to src/ioprobe.egg-info/top_level.txt
writing dependency_links to src/ioprobe.egg-info/dependency_links.txt
writing entry points to src/ioprobe.egg-info/entry_points.txt
reading manifest file 'src/ioprobe.egg-info/SOURCES.txt'
writing manifest file 'src/ioprobe.egg-info/SOURCES.txt'
running check
creating ioprobe-0.1.2
creating ioprobe-0.1.2/src
creating ioprobe-0.1.2/src/ioprobe
creating ioprobe-0.1.2/src/ioprobe.egg-info
copying files to ioprobe-0.1.2...
copying NEWS.txt -> ioprobe-0.1.2
copying README.rst -> ioprobe-0.1.2
copying setup.py -> ioprobe-0.1.2
copying src/ioprobe/__init__.py -> ioprobe-0.1.2/src/ioprobe
copying src/ioprobe/helper.py -> ioprobe-0.1.2/src/ioprobe
copying src/ioprobe/test_ioprobe.py -> ioprobe-0.1.2/src/ioprobe
copying src/ioprobe.egg-info/PKG-INFO -> ioprobe-0.1.2/src/ioprobe.egg-info
copying src/ioprobe.egg-info/SOURCES.txt -> ioprobe-0.1.2/src/ioprobe.egg-info
copying src/ioprobe.egg-info/dependency_links.txt -> ioprobe-0.1.2/src/ioprobe.egg-info
copying src/ioprobe.egg-info/entry_points.txt -> ioprobe-0.1.2/src/ioprobe.egg-info
copying src/ioprobe.egg-info/not-zip-safe -> ioprobe-0.1.2/src/ioprobe.egg-info
copying src/ioprobe.egg-info/requires.txt -> ioprobe-0.1.2/src/ioprobe.egg-info
copying src/ioprobe.egg-info/top_level.txt -> ioprobe-0.1.2/src/ioprobe.egg-info
Writing ioprobe-0.1.2/setup.cfg
Creating tar archive
removing 'ioprobe-0.1.2' (and everything under it)
running upload
Submitting dist/ioprobe-0.1.2.tar.gz to https://test.pypi.org/legacy/
Server response (200): OK
|
twineでアップロードする
1
2
3
4
5
6
7
8
9
10
|
$ twine upload --repository pypitest dist/*
Uploading distributions to https://test.pypi.org/legacy/
Uploading ioprobe-0.1.1-py2-none-any.whl
100%|############################################################| 11.5k/11.5k [00:03<00:00, 3.32kB/s]
Uploading ioprobe-0.1.2-py2-none-any.whl
100%|############################################################| 11.5k/11.5k [00:02<00:00, 5.42kB/s]
Uploading ioprobe-0.1.1.tar.gz
100%|############################################################| 10.4k/10.4k [00:02<00:00, 4.29kB/s]
Uploading ioprobe-0.1.2.tar.gz
100%|############################################################| 10.4k/10.4k [00:01<00:00, 9.83kB/s]
|