Don't writing python scripts, writing python libraries.
Don't writing python scripts, writing python libraries.
はじめに
pythonでscriptを書いていくだけだと辛い事が多い。 たとえ、作成するアプリでは使われないコードであってもライブラリとして作っておいた方が良い。 具体的には以下の様にする。
- misc的なものもpython packageにする
- 作ったパッケージをeditable modelでinstallする
- bin 以下に置きたいスクリプトは自前のmisc libraryを呼ぶようにする
- (sys.path考えてのcwdの調整はダメ絶対)
これを守ると結構スクリプトを書く時の苦労が減る。 個人的には本番では利用せず手元で利用するような便利スクリプト系の機能を書く際に利用するproject特有のmisc libraryという位置付けのpackageを作ったら捗った(後々成長してきた場合にはpackageを分割するかもしれない)。
misc packageの作り方
ここで言う、misc packageというのは、各プロジェクトリポジトリ内に一緒に管理されるpython packageのことで、特にpypiにuploadされるなどは念頭に入れていない。
pythonのvenv環境作成
綺麗な環境があると便利なのでvirtualenvを使うことにする。既に環境が存在している人はここを飛ばしても良い。 例えば、冒頭のmisc packageを作るという話であれば既存のprojectの環境で良いと思う。
# sudo pip install virtualenv virtualenv foo --python=`which python3.4` cd foo . bin/activate
virtualenvの環境を手軽に有効にするためにvirtualenv wrapperなどを使う人もいるらしいが。個人的には以下のような設定が.bashrcなどにあれば十分だと思っている。
alias foo=". ~/venvs/foo/bin/activate && cd ~/venvs/foo/"
cookiecutterのインストール
残念ながらpythonには標準でpackageを作るためのscaffold(project template)が付いていない。 packageの作成に慣れた人であれば、自分用のscaffoldを持っていたり、必要十分な設定を熟知していたりするかもしれないが、ココでは作業コストを下げるためにどうするかということを考えたい。
今おそらく一番メジャーなpackage templateは cookiecutter だと思うのでこれを使うことにする。
pip install cokkiecutter
環境作成時にinstallされたpackageのversionの違いで右往左往したくなければversionを固定しておいても良いかもしれない プロダクション運用では不要なパッケージではある可能性があるのでrequirements.txtという名前のファイルではなくrequirements-dev.txtという名前にしている。
pip freeze | tee requirements-dev.txt binaryornot==0.4.0 chardet==2.3.0 click==5.1 cookiecutter==1.2.1 future==0.15.2 Jinja2==2.8 MarkupSafe==0.23 ruamel.base==1.0.0 ruamel.yaml==0.10.12 wheel==0.24.0 whichcraft==0.1.1
coockiecutterの利用
python package用のproject templateには以下の2種類があるがとりあえずminimalの方を使う。
- cookiecutter-pypackage: @audreyr's ultimate Python package project template.
- cookiecutter-pypackage-minimal: A mimimal Python package template.
気に入らないところが出てきたら自分でproject templateを書くことになるかもしれない。とりあえず最初の内はてきとうにあるものを使うという方針で行く。後々気に入らない部分を直すことを考えると手元にcloneして使った方が便利かもしれない。
とりあえず sandbox
という名前のpackageを作ることにする
git clone https://github.com/borntyping/cookiecutter-pypackage-minimal.git cookiecutter cookiecutter-pypackage-minimal author_name [Louis Taylor]: podhmo podhmo author_email [louis@kragniz.eu]: ababjam61@gmail.com package_name [cookiecutter-pypackage-minimal]: sandbox package_version [0.1.0]: package_description [An opinionated, minimal cookiecutter template for Python packages]: package_url [https://github.com/borntyping/cookiecutter-pypackage-minimal]: readme_pypi_badge [True]: readme_travis_badge [True]: readme_travis_url [https://travis-ci.org/borntyping/cookiecutter-pypackage-minimal]:
(travis用の設定など邪魔なので消したい) 今回作っているのはpypiなどに公開しない単なるmisc的なものをまとめるためのpackageなのであまり色々拘る必要はない。以下の事が確認できれば良い。
- installできるかどうか
- importして使えるかどうか
- テストが実行できるかどうか
インストール自体はeditable modeで行う。
cd sandbox pip install -e . python setup.py test running test
残念ながらすぐにテストが実行されるようには設定されなかった。以下の追加の作業が必要。
mkdir sandbox/tetsts/ touch sandbox/tetsts/__init__.py
setup.pyも書き換える。
diff --git a/setup.py b/setup.py index f9b72fd..926c4ba 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,8 @@ setuptools.setup( description="An opinionated, minimal cookiecutter template for Python packages", long_description=open('README.rst').read(), - packages=setuptools.find_packages(), + packages=setuptools.find_packages(exclude=["tests.*"]), + test_suite="sandbox.tests", install_requires=[],
テストが動くようになった。
$ python setup.py test running test running egg_info writing sandbox.egg-info/PKG-INFO writing dependency_links to sandbox.egg-info/dependency_links.txt writing top-level names to sandbox.egg-info/top_level.txt reading manifest file 'sandbox.egg-info/SOURCES.txt' writing manifest file 'sandbox.egg-info/SOURCES.txt' running build_ext ---------------------------------------------------------------------- Ran 0 tests in 0.000s OK
作業としてはこれで終わり。後は開発環境ではこのpackageをインストールしておくようにrequirements-dev.txtを書き換える
-e ./sandbox
作ったpackageがインストールできることを確認しておく。
$ python Python 3.4.2 (default, Oct 15 2014, 21:23:36) [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import sandbox >>> sandbox.__version__ '0.1.0' >>> ^D
いろいろ直したい部分が見つかるので自分でproject templateを書き直すことになりそう。
参考
真面目に頑張りたい場合にはpypaの情報を見ると良い。