PyPIにデビューした

PyPIデビューした

〜 PyPIデビューまでの道のり 〜

大阪Pythonユーザの集まり 2015/12

whoami

icon

名前:
ごうじん (山田 剛人:やまだ たけひと)
所属:フリーランス
出身:兵庫県播磨南西部
Python歴:2年
お気に入り:Tornado, PyZMQ

PyPIってなに

PyPIとは


  • Python Package Indexの略で、プログラミング言語Pythonのサードパーティソフトウエアのリポジトリ。

  • Javaで言うと、Maven Central Repository、PHPならREAR、Node.jsは、npmjsにあたります。

  • 使いたいモジュールをインストールしたい時に、
    pip install .. とか、 easy_install .. とかしたことあると思いますが、その時に接続しているサーバになります。

Python Package Index - https://ja.wikipedia.org/wiki/Python_Package_Index より引用

PyPIとは

$ easy_install -U tornado
Searching for tornado
Reading https://pypi.python.org/simple/tornado/
Best match: tornado 4.3
Downloading https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz#md5=d13a99dc0b60ba69f5f8ec1235e5b232
Processing tornado-4.3.tar.gz
Writing /var/folders/dr/13__6q953t10jkm2vttcbnbh0000gn/T/easy_install-KaS1w2/tornado-4.3/setup.cfg

                                  :
                                  :

Adding tornado 4.3 to easy-install.pth file

Installed /Users/gaujin/osakapy/lib/python2.7/site-packages/tornado-4.3-py2.7-macosx-10.11-intel.egg
Processing dependencies for tornado
Finished processing dependencies for tornado

PyPIとは

$ easy_install -U tornado
Searching for tornado
Reading https://pypi.python.org/simple/tornado/
Best match: tornado 4.3
Downloading https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz#md5=d13a99dc0b60ba69f5f8ec1235e5b232
Processing tornado-4.3.tar.gz
Writing /var/folders/dr/13__6q953t10jkm2vttcbnbh0000gn/T/easy_install-KaS1w2/tornado-4.3/setup.cfg

                                  :
                                  :

Adding tornado 4.3 to easy-install.pth file

Installed /Users/gaujin/osakapy/lib/python2.7/site-packages/tornado-4.3-py2.7-macosx-10.11-intel.egg
Processing dependencies for tornado
Finished processing dependencies for tornado

PyPIデビュー動機

動機(1)

  • PyConJP 2015で @tell_k さんのセッションを聴いて、自分もデビューしてみたいと思った。

tel-k

全面的に参考にさせていただきました。
ありがとうございます。

動機(2)

  • PyConJP 2015で「やきうの人( @shinyorke さん)」に crontab ネタを引用していただいたことで、「もしかしたら需要あるかも」と思った。

どんなパッケージにするか

どんなパッケージにするか



  • どうせデビューするなら、仕事に活かせるパッケージにしたい。

  • 仕事で使っている Tornado を拡張できるものにしたい。



どんなパッケージにするか



  • Tornado と crontab(parse-crontab) で、cronのような定時処理をさせたい。
    ※Tornadoには 定期処理機構 はあるが、 定時処理機構 はない。

  • 大規模にやるなら、Celeryのようなタスクフレームワークを使えばいいが、バックエンドを持たなくても実現できる方がいい。

Tornadoとは


  • Pythonで書かれたスケーラブルでノンブロッキングなWebサーバ、Webフレームワークである。

  • FriendFeedによって開発され、Facebookに吸収されたのちにオープンソース化された。

Tornado (Webサーバ) - ウィキペディア - https://ja.wikipedia.org/wiki/Tornado_(Webサーバ) より引用

crontab(parse-crontab)とは


  • Josiah Carlson さん作成の、crontab書式から、次回実行時間までの待ち時間を計算してくれる小さなパッケージ。

出来上がったソースコードがこちら

ソースコード

tornado-crontab_source

https://github.com/gaujin/tornado-crontab

今回使ったもの


  • ソースコードエディタ(IDE)

  • ソースコード公開リポジトリ

  • 自動テストツール

  • 依存モジュールのチェックツール

  • 予行演習用PyPI

今回使わなかったもの


  • ドキュメント公開ツール

  • カバレッジツール

  • コード品質チェックツール

ソースコードエディタ(IDE)

pydev_logo

ソースコードエディタ(IDE)

pydev

ソースコードエディタ(IDE)

tips_pydev_filter1

PyDevは、ドットで始まるリソースファイルは、デフォルト表示されないので、フィルタを変更しておく。

ソースコードエディタ(IDE)

tips_pydev_filter2

ドット以外のファイルもお好みで設定してください。

ソースコード公開リポジトリ


  • ソースコードは、自分のホームページやブログなどで公開してもよい。

  • 修正履歴やバグ報告を公開するほうが透明性があり、信用される。

  • バージョン管理サービスを使うのがお手軽。

  • 外部の連携サービスが豊富な方がよい。

  • 今回は、Githubを使いました。

ソースコード公開リポジトリ

github_portal

継続的インテグレーション(CI)


  • 開発中・開発後に、想定する環境を用意してテストするのは、時間がかかるし面倒。

  • 自前で環境を整えるのも良いが、CIサービスを使うのが手っ取り早くて便利。

  • Githubと連携できる、 Travis CI を今回は使いました。

継続的インテグレーション(CI)

travisci_portal

Travis CI


  • ソースコードリポジトリのトップディレクトリに .travis.yml を配置しておくと、そのレシピどおりにビルド・テストしてくれる。

Travis CIを使うメリット

tips_travisci_buildlog

ビルド結果をログで確認できる。

Travis CI を使うメリット

tips_travisci_mail_notify

ブランチとタグのビルド結果を、メール通知してくれる。

Travis CI を使うメリット


tips_travisci_badge

ビルド結果のバッジでさりげなくアピール。

Travis CI tips


  • コミットコメントに [ci skip] と書いておくと、Travis CI ではビルドの対象としない。

  • タグはコミットに付くので、 [ci skip]につけたタグもビルドの対象にならない。

依存モジュールの鮮度を知る


  • 開発している間に、依存しているモジュールがアップデートされて全く動かない...ようなことがないように、常に鮮度を確認することが大切。

  • 依存モジュールを確認してくれる Requires.io を使って、自動的に確認してもらうことにしました。

依存モジュールの鮮度を知る

requiresio_portal

Requires.io を使うメリット


  • 条件にマッチするファイルは全てチェックしてくれる。

    • setup.py
    • req*.txt または req*.pip
    • requirements/*.txt または requirements/*.pip
    • buildout.cfg と versions.cfg
    • tox.ini

Requires.io を利用するメリット


tips_requiresio_badge

チェック結果のバッジを、 Travis CI のバッチと
合わせて使うとなんか気持ちいい。

PyPIデビューの予行演習


  • PyPIにいきなり登録するのは不安。

  • PyPIには、演習用サイト testpypi が用意されている。

  • パッケージの概要や、内容、バージョン管理の方法などを試すことができます。

PyPIデビューの予行演習

testpypi_package_editing

“TESTING SITE”ラベルが目印

PyPIデビューの予行演習

testpypi_registration

アカウントの登録申請をする

PyPIデビューの予行演習

testpypi_registration_confirm

入力内容の確認をする

PyPIデビューの予行演習

testpypi_registration_mail

メールに添付されたリンクをクリックする

PyPIデビューの予行演習

testpypi_registration_complete

アカウント登録完了

PyPIデビューの予行演習

~/.pypirc
$ cat <<EOF > ~/.pypirc
[distutils]
index-servers =
    testpypi

[testpypi]
repository: https://testpypi.python.org/pypi
username: ユーザ名
password: パスワード
EOF

.pypircファイルを用意する

PyPIデビューの予行演習

git clone
$ git clone https://github.com/gaujin/tornado-crontab.git
Cloning into 'tornado-crontab'...
remote: Counting objects: 114, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 114 (delta 0), reused 0 (delta 0), pack-reused 108
Receiving objects: 100% (114/114), 14.57 KiB | 0 bytes/s, done.
Resolving deltas: 100% (51/51), done.
Checking connectivity... done.

登録したいソースコードをクローンする

PyPIデビューの予行演習

git checkout
$ git checkout refs/tags/v0.2
Note: checking out 'refs/tags/v0.2'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 50dc188... deleted Framework classifier

testpypiに登録するタグに切り替える

PyPIデビューの予行演習

python setup.py register -vnr testpypi
$ python setup.py register -vnr testpypi
running register
running egg_info
writing requirements to tornado_crontab.egg-info/requires.txt
writing tornado_crontab.egg-info/PKG-INFO
writing top-level names to tornado_crontab.egg-info/top_level.txt
writing dependency_links to tornado_crontab.egg-info/dependency_links.txt
reading manifest file 'tornado_crontab.egg-info/SOURCES.txt'
writing manifest file 'tornado_crontab.egg-info/SOURCES.txt'
running check
Registering tornado-crontab to https://testpypi.python.org/pypi
Server response (200): OK

testpypiにパッケージを登録する

PyPIデビューの予行演習

python setup.py sdist upload -r testpypi
$ python setup.py sdist upload -r testpypi
running sdist
running egg_info
writing requirements to tornado_crontab.egg-info/requires.txt
writing tornado_crontab.egg-info/PKG-INFO
writing top-level names to tornado_crontab.egg-info/top_level.txt
writing dependency_links to tornado_crontab.egg-info/dependency_links.txt
reading manifest file 'tornado_crontab.egg-info/SOURCES.txt'
writing manifest file 'tornado_crontab.egg-info/SOURCES.txt'
running check
creating tornado-crontab-0.2
creating tornado-crontab-0.2/tornado_crontab
creating tornado-crontab-0.2/tornado_crontab.egg-info

                             :
                             :

Creating tar archive
removing 'tornado-crontab-0.2' (and everything under it)
running upload
Submitting dist/tornado-crontab-0.2.tar.gz to https://testpypi.python.org/pypi
Server response (200): OK

testpypiにパッケージをアップロードする

これで、パッケージが公開されたので、パッケージのページを見てみましょう。

PyPIデビューの予行演習

testpypi_package_error

なっ...なんじゃこれは...

PyPIデビューの予行演習

with codecs.open(os.path.join(here, "README.rst"), encoding="utf8") as f:
    long_description = f.read()

setup(

                 :
                 :

    description=long_description,

                 :
                 :
)

説明に長い方を入れていたからですね。

PyPIデビューの予行演習

testpypi_submit_package_info

ソースは直さずに、パッケージ管理画面で編集できます。
※本番はソースコードを直したものを使いました。

改めて、パッケージのページを見てみましょう。

PyPIデビューの予行演習

testpypi_package

綺麗に表示されました。これで予行演習は終わりですね。

いよいよPyPIデビュー


  • testpypiで一通り慣れたら、いよいよ、PyPIに登録してデビューです。

  • testpypiとPyPIのアカウントは共通ではないので、testpypiと同様に、アカウントの取得からとなります。

  • 手順は testpypi と全く同じです。

PyPIデビュー

pypi_registration

アカウントの登録申請をする

PyPIデビュー

pypi_registration_confirm

入力内容の確認をする

PyPIデビュー

pypi_registration_mail

メールに添付されたリンクをクリックする

PyPIデビュー

pypi_registration_complete

アカウント登録完了

PyPIデビュー

~/.pypirc
$ vi ~/.pypirc
$ cat ~/.pypirc
[distutils]
index-servers =
    pypi
    testpypi

[pypi]
repository: https://pypi.python.org/pypi
username: ユーザ名
password: パスワード

[testpypi]
repository: https://testpypi.python.org/pypi
username: ユーザ名
password: パスワード

.pypircファイルにPyPIの情報を追加します。

PyPIデビュー

git clone
$ git clone https://github.com/gaujin/tornado-crontab.git
Cloning into 'tornado-crontab'...
remote: Counting objects: 114, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 114 (delta 0), reused 0 (delta 0), pack-reused 108
Receiving objects: 100% (114/114), 14.57 KiB | 0 bytes/s, done.
Resolving deltas: 100% (51/51), done.
Checking connectivity... done.

登録したいソースコードをクローンする

PyPIデビュー

git checkout
$ git checkout refs/tags/v0.2
Note: checking out 'refs/tags/v0.2'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 50dc188... deleted Framework classifier

pypiに登録するタグに切り替える

PyPIデビュー

python setup.py register -vnr pypi
$ python setup.py register -vnr pypi
running register
running egg_info
writing requirements to tornado_crontab.egg-info/requires.txt
writing tornado_crontab.egg-info/PKG-INFO
writing top-level names to tornado_crontab.egg-info/top_level.txt
writing dependency_links to tornado_crontab.egg-info/dependency_links.txt
reading manifest file 'tornado_crontab.egg-info/SOURCES.txt'
writing manifest file 'tornado_crontab.egg-info/SOURCES.txt'
running check
Registering tornado-crontab to https://pypi.python.org/pypi
Server response (200): OK

pypiにパッケージを登録する

PyPIデビュー

python setup.py sdist upload -r pypi
$ python setup.py sdist upload -r pypi
running sdist
running egg_info
writing requirements to tornado_crontab.egg-info/requires.txt
writing tornado_crontab.egg-info/PKG-INFO
writing top-level names to tornado_crontab.egg-info/top_level.txt
writing dependency_links to tornado_crontab.egg-info/dependency_links.txt
reading manifest file 'tornado_crontab.egg-info/SOURCES.txt'
writing manifest file 'tornado_crontab.egg-info/SOURCES.txt'
running check
creating tornado-crontab-0.2
creating tornado-crontab-0.2/tornado_crontab
creating tornado-crontab-0.2/tornado_crontab.egg-info

                             :
                             :

Creating tar archive
removing 'tornado-crontab-0.2' (and everything under it)
running upload
Submitting dist/tornado-crontab-0.2.tar.gz to https://pypi.python.org/pypi
Server response (200): OK

pypiにパッケージをアップロードする

PyPIデビューした

これで、めでたくPyPIデビューとなりました。

tornado-crontabの紹介

例えば

/path/to/this.py
from __future__ import print_function

def hello_crontab(value):

    print("Hello, {}".format(value))

if __name__ == "__main__":

    hello_crontab("crontab")
crontab -e
* * * * * /path/to/this.py > /tmp/this.log 2>&1

tornado-crontab

install
$ easy_install tornado-crontab
/path/to/this.py
from __future__ import print_function
import tornado.ioloop
from tornado_crontab import crontab

@crontab("* * * * *")
def hello_crontab(value):

    print("Hello, {}".format(value))

if __name__ == "__main__":

    hello_crontab("crontab")
    tornado.ioloop.IOLoop.instance().start()
run
/path/to/this.py > /tmp/this.log 2>&1 &

今後は...

  • tornado-crontabに排他機能を付けたい
  • toxを使って、各Pythonバージョンをテストしたい
  • Read The Docsに、ドキュメントを置きたい
  • Coverallsデビューしたい
  • Code Climateデビューしたい
  • Tornadoも使わないパッケージを作りたい

PyPIデビュー成果

ご清聴ありがとうございました。