Mediumで以下のような記事があった
Goodbye Virtual Environments? – Chad Smith – Medium
さようなら、仮想環境?
記事を見る感じ、python と pip の代わりになるようなコマンドっぽい
また、PEP582で提案されている__pypackages__
が使われている
ソースコードを見たり、READMEを見たり、Medinumを見たりしただけなので、間違いがあるかもしれません。
間違いがありましたら、教えていただけると嬉しいです。
動作環境
Python 3.7.1
pythonloc
pythonとpipを使って実装されている小さなプロジェクト
仮想環境がいらなくなりそうな予感!?
pythonlocのコマンド
以下のコマンドと対応している
通常 | pythonlocを使うと... |
---|---|
$ python | $ pythonloc |
$ pip | $ piploc |
$ pip freeze > requirements.txt | $ pipfreezeloc > requirements.txt |
piplocコマンド
pip
の代わり
$ piploc install {pkg}
./__pypackages__/{version}/lib
内にpkg
がインストールされる
pipでのインストール先が./__pypackages__/{version}/lib
となる
pythonlocコマンド
python
の代わり
$ pythonloc
PYTHONPATHに、.:__pypackages__/{version}/lib:$PYTHONPATH
を設定された状態で、python
(sys.executable)が実行される
pipfreezelocコマンド
pip freeze
の代わり
$ pipfreezeloc
。・__pypackages__/{version}/lib
内のパッケージの情報を出力する
pythonlocの何がすごいと思ったのか
pipenv shell
みたいに仮想環境の有効化をしなくてもよくなる
これは、モジュールの検索順序の仕組みを利用してうまく実装されている
まず、Pythonはモジュールのインポートをするときに、インポートするモジュールをsys.pathから検索する。
このsys.path
についての説明は、ドキュメントに書いてあった
spam という名前のモジュールをインポートするとき、インタープリターはまずその名前のビルトインモジュールを探します。見つからなかった場合は、 spam.py という名前のファイルを sys.path にあるディレクトリのリストから探します。 sys.path は以下の場所に初期化されます:
・入力されたスクリプトのあるディレクトリ (あるいはファイルが指定されなかったときはカレントディレクトリ)。
・PYTHONPATH (ディレクトリ名のリスト。シェル変数の PATH と同じ構文)。
・インストールごとのデフォルト。
pythonlocでは、PYTHONPATH
に.:__pypackages__/{version}/lib:$PYTHONPATH
を設定することによって、優先的に検索しに行くようにしている
PYTHONPATHに.:__pypackages__/{version}/lib:$PYTHONPATH
を設定している
PYTHONPATHについては、ドキュメントを参照
まず、通常のpythonの場合
$ python
>>> import sys, os, pprint
>>> os.environ.get('PYTHONPATH', '')
''
>>> pprint.pprint(sys.path)
['',
'temp/test/pythonloc',
'/Users/tamago324/.pyenv/versions/3.7.1/lib/python37.zip',
'/Users/tamago324/.pyenv/versions/3.7.1/lib/python3.7',
'/Users/tamago324/.pyenv/versions/3.7.1/lib/python3.7/lib-dynload',
'/Users/tamago324/.local/lib/python3.7/site-packages',
'/Users/tamago324/.pyenv/versions/3.7.1/lib/python3.7/site-packages']
次に、pythonlocの場合
$ pythonloc
>>> import sys, os, pprint
>>> os.environ.get('PYTHONPATH', '')
'.:__pypackages__/3.7/lib:'
>>> pprint.pprint(sys.path)
['',
'/temp/test/pythonloc',
# ここに追加されている
'/Users/tamago324/src/python/test/pythonloc/__pypackages__/3.7/lib',
'/Users/tamago324/.pyenv/versions/3.7.1/lib/python37.zip',
'/Users/tamago324/.pyenv/versions/3.7.1/lib/python3.7',
'/Users/tamago324/.pyenv/versions/3.7.1/lib/python3.7/lib-dynload',
'/Users/tamago324/.local/lib/python3.7/site-packages',
'/Users/tamago324/.pyenv/versions/3.7.1/lib/python3.7/site-packages']
このように、__pypackages__/{version}/lib
は、/Users/tamago324/.pyenv/versions/3.7.1/lib/python3.7/site-packages
よりも前にあるため、__pypackages__/{version}/lib
が優先的に検索されるようになる
まとめ
pythonlocの考え方すごい。__pypackages__
すごい。PEP582すごい。