search
LoginSignup
17

posted at

updated at

__version__ ってアンチパターンじゃね?

Python のライブラリでは、よく __version__ が定義されていて、
インタラクティブシェルで、簡便なバージョン確認に使えますが、

>>> import pandas
>>> pandas.__version__
'0.21.0'

自分でライブラリを書くのに、__verson__ を定義するのはアンチパターンじゃないかと、最近思い始めました。

じゃあどうするの?

こうします。

  • __version__ は定義しない
  • バージョンは setup.py に(だけ)指定する

以下理由です。

理由1: 二重管理になる

バージョン番号は、setup.pyにも書かなくていけません。

# mylibrary.py
__version__ = '1.2.3'
# setup.py
from setuptools import setup
import mylibrary

setup(
  version='1.2.3',
  ...
)

ファイルを2つ編集するのは面倒ですね。
面倒だけならまだいいのですが、両者のバージョンがズレてしまったらどうするのか?バージョンを合わせるだけのために、新しいバージョンをリリースするのか?

理由2: setup.py が本体のコードに依存してしまう

二重管理を避けるために、setup.py で__version__を参照する方法もよく取られています。

# setup.py
from setuptools import setup
import mylibrary

setup(
  version=mylibrary.__version__,
  ...
)

しかしこれは、mylibrary がどこでも容易にimportできることを暗黙に仮定しています。もし、

  • mylibrary が内部で他のライブラリに依存していたら?
  • mylibrary がC言語拡張モジュールだったら?
  • mylibrary が import にすごく時間がかかる巨大なライブラリだったら?

特に1番目のケースでは、依存ライブラリのインストールに setup.py を実行しなけりゃならないが、mylibrary が import できないので setup.py が実行できない!

って状況になります。

理由3: 無くても困らない

そんなにバージョンを知りたいですか?

別に、バージョンを知りたければ、pip freeze コマンドでよくないですか?

$ pip freeze | grep mylibrary
mylibrary==1.3.4

依存ライブラリのバージョンごとに振る舞いを変えるために、こんなポリフィルを書くことがありますが、

if mylibrary.__version__ >= '1.4.0':
   something = mylibrary.something
else:
   def something():
      mylibrary.something のポリフィル

しかし、そもそもこれは適切なのか?

バージョン関係の処理は ライブラリの責務なのでしょうか?。
あんまり頑張るのではなく、単に古い依存ライブラリは切ってしまう。それが、古いライブラリの更新を促し、結果的にみんなが幸せになるのではないかとも思います。

なお、どうしてもプログラム的にバージョンを取りたいなら、pkg_resources を使うこともできます。

import pkg_resources
v = pkg_resources.get_distribution('mylibrary').version

理由4: そもそも標準でもなんでもない

__version__ はなんとなくみんな定義しているだけで、定義しなくてもよいものです。「__version__ を追加してください」ってIssueは建てられるかもしれませんが。

標準では無いので、バージョンを確実に取得したいなら、上述のpkg_resources を使わざるをえません。そして、pkg_resources では __version__ は不要です。

感想

SQLアンチパターンみたいな本を読むと、アンチパターンって、「簡単にできる」とか「一見シンプル」なものが多いような気がするんですが、__version__ はまさにそれだなって思います。初心者でも簡単にできるし、一見シンプルで賢そうな解決。でも後々困る。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
17