今どきのPythonのライブラリ自作からPyPIへの登録

  • 160
    いいね
  • 3
    コメント
この記事は最終更新日から1年以上が経過しています。

自分のライブラリをPyPIに登録したい

...が、PythonにはRubyのbundlerのようなものが
なく、(合ったとしても統一されてないと思う)
プロダクト別に自由なディレクトリ構成になっている状態...

せめて自分のプロダクトについては統一したいなあと思ったので
Pythonのライブラリを作る場合のディレクトリ構成や
環境構築などについてメモを書く。忘れちゃうので...

利用するPythonのバージョンは3.3以降を意識してる。
それより前(3.2, 3.1...2.x)は考慮しない。問題無いと思うけど...

テスト目的で作成したライブラリ

スクリーンショット 2013-10-16 8.08.53.png

fizzbuzzというアレなライブラリを作った。
ライブラリというかコマンドラインツールだけれど。
このライブラリの構成を元に、メモを書いていく。

ライブラリのディレクトリ・ファイル構成

以下のディレクトリ・ファイル構成とする。

fizzbuzz
└lib # ライブラリ本体
  └bin # 実行スクリプト本体
  └fizzbuzz # ライブラリ名のディレクトリ
      └ __init__.py # ライブラリimport時の初期化設定はここで 
  └test # テストファイル
requirements.txt # travis-ci及びsetup.pyで利用する。pip --freezeで作れる。
info.py # パッケージの作者情報などを収めるファイル
version.py # バージョン情報を収めるファイル
setup.py #キモとなるファイル

こういうのでいいんじゃないかな。

pyvenvの環境をライブラリディレクトリ以下に構築する

Python 3.3より、virtualenv が包含された。
ライブラリの動作テストを行うために、以下のコマンドで
ローカルなPython実行環境を作成する。

> pyvenv .venv

virtualenvの頃から使っているため、.venv以下に
pyvenvの環境を作るようにしているが、任意で良いと思う(.pvenvとか)。

ローカルなPython実行環境を構築したので、
activate を shellのsource コマンドにて取り込む。
こうすることで、.venv 以下のPython環境を使う形になる。(pythonコマンドとか)

> source .venv/bin/activate

setuptoolsのインストール

virtualenvのとあるバージョンまでは
システムのライブラリをvirtualenvで取り込んでくれたりしたけど、
virtualenvの新しいバージョン及びpyvenvだと取り込んでもらえない。
pyvenvを実行するとピュアな環境が構築される。

そのため、easy_install が無い状態で環境が作られる。
以下のコマンドを実行してsetuptools をセットアップしよう。

setuptoolsのPyPIページより引用。

> wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python

これでeasy_installコマンドを実行し、PyPIにある
パッケージをインストールできるようになる。
が、easy_installでPyPIのパッケージをインストールするより、
pip を使うほうが使いやすい。pipを入れよう...

pip のインストール

easy_installを入れている状態であれば、pipは気軽にインストールすることができる。

> easy_install pip

以上で準備完了。

必要なライブラリのリストを作成する

自作ライブラリが他のライブラリを使っている場合、
setuptools.setup 関数に渡すhashに
install_requiresを指定しないといけない。
pipを利用すると気軽に必須ライブラリのリストを作ることができる。

> pip freeze > requirements.txt

TravisCIもrequirements.txtを利用するので

setup.pyにて、requirement.txt を利用してinstall_requiresを指定するようにする。

setup({
  install_requires: open('requirements.txt').read().splitlines(),
})

これでライブラリが必要としている外部ライブラリがインストールされる。

パッケージの情報をどこに持たせるか

パッケージ作成者の情報

PyPIで表示されるライブラリ作成者の情報について、どのファイルに持たせるか
なんか迷ったけど、package root直下にinfo.py として置く形にした。

info.py
# package information.
INFO = dict(
  name        = "PyFizzBuzz",
  description = "FizzBuzz cli tool",
  author      = "Keiji Matsuzaki",
  author_email = "futoase@gmail.com",
  license     = "MIT License",
  url         = "https://github.com/futoase/fizzbuzz",
  classifiers = [
    "Programming Language :: Python :: 3.2",
    "Programming Language :: Python :: 3.3",
    "License :: OSI Approved :: MIT License"
  ]
)

classifiersは、ここのリストより自分のライブラリが
マッチしてそうなジャンルを選択し、設定する。

パッケージバージョン

version.py の中にVERSIONを指定する。

version.py
VERSION = "0.0.3"

MANIFEST.in ファイルの作成

20131017追記

package_dir ではinfo.py, version.py, requirements.txt ファイルを指定していないため、
MANIFEST.inファイルを書かないといけない。
この記事を書いたときにチェックを怠って居たため、includeされていない問題を発見できませんでした。
ので追記。

MANIFEST.in
include info.py
include version.py
include requirements.txt

パッケージのテスト

pipコマンドを利用し、パッケージのテストを行う

> pip install .

自分自身のディレクトリ内で自分自身を指定してpip installを行うことで、
pyvenv の環境内で自己のライブラリを利用することができる。

> pip list
konira (0.3.2)
pip (1.4.1)
PyFizzBuzz (0.0.3)
setuptools (1.1.5)

もし、pip install後、自分のライブラリにバグが合った場合は
pyvenvの環境以下で以下のコマンドを実行すれば良い。

> pip uninstall PyFizzBuzz

Gemfileにgemspec を指定するような...気持ちでコマンドを実行すればいいと思う...

動作チェック

今回、fizzbuzzはコマンドとして実行されるようにしたので、
.venv/bin/fizzbuzz にコマンドが置かれている。

(.venv) > fizzbuzz 10 | head -3        
1
2
Fizz

動作チェックは行えた。

PyPIへの登録

PyPIへの登録を行っていない場合は、以下のコマンドを実行し、登録する。

~/.piprc ファイルを生成していない場合はユーザー名、パスワードの登録を促される(はず)...

> python setup.py register

PyPIへパッケージのアップロードを行う。

> python setup.py sdist upload

PyPIにライブラリのページが作成されればOK

C拡張のライブラリの場合は異なるかもしれない。
(eggファイルのアップロードについては考慮していない...)

PyPIへのアップロード後

一日のダウンロード数や、過去にアップロードしたバージョンのファイルの一覧などを
PyPIページから見ることができる。(要ログイン済)

結構楽しい。

余談

setuptoolsがdistributeと統合されたので、setuptoolsのみimportしている形になったけど、
統合される前は以下の形でsetup.pyにてimportするパッケージの切り分けをしていた。

setup.py
try:
    import setuptools
except ImportError:
    from distribute_setup import use_setuptools
    use_setuptools()
from setuptools import setup, find_packages

distribute_setup.pyをここから落として(なんか書いてる今アクセスできないや)、パッケージに含める形で対応していた。

setuptoolsに統一されてよかった。(この記事では下位互換性のことは考慮してないからこうできるのかもしれない...)