pip freezeで上手く出力されない場合(@ file:~~となってしまう場合）

この記事では、Anacondaで作成した仮想環境上で動作しているPythonについて書いています。
Pythonのpipコマンドには色々な機能があります。
PyPI上のモジュールをインストールする機能が1番有名ですが、現在の環境（または仮想環境）にインストールされているモジュールを一覧で表示したいときは以下のコマンドを使います。

~~~
pip list
~~~

上記のコマンドを実行すると、現在の環境にインストールされているモジュールの一覧が表示されます。
（今後、インストールされたモジュールを画面に出力したものを記載する時は、分かりやすいように１０個程度だけを選んで記載しますので、その点ご注意ください）


~~~
Package                   Version
------------------------- ---------
altgraph                  0.17.2
cycler                    0.11.0
distlib                   0.3.6
fonttools                 4.37.1
future                    0.18.2
lxml                      4.9.1
matplotlib                3.5.3
numpy                     1.23.2
openpyxl                  3.0.10
packaging                 21.3
pandas                    1.4.3
Pillow                    9.2.0
pip                       22.2.2
pyparsing                 3.0.9
python-dateutil           2.8.2
pytz                      2022.2.1
setuptools                65.3.0
six                       1.16.0
virtualenv                20.16.3
~~~

また、pip freezeというコマンドがあり、これは現在の環境（インストールされているモジュール名）とバージョンを==でつないだ、要件形式で出力します。

~~~
pip freeze
~~~

~~~
altgraph==0.17.2
cycler==0.11.0
distlib==0.3.6
fonttools==4.37.1
future==0.18.2
lxml==4.9.1
matplotlib==3.5.3
numpy==1.23.2
openpyxl==3.0.10
packaging==21.3
pandas==1.4.3
Pillow==9.2.0
pyparsing==3.0.9
python-dateutil==2.8.2
pytz==2022.2.1
six==1.16.0
virtualenv==20.16.3
~~~

また、pip freezeを「>」のリダイレクト記号をつないで、テキストに出力し、依存関係のあるモジュールを一発でインストールする方法が有名です。

~~~
pip freeze > requirements.txt
~~~

これを実行すると、pip freezeを実行した時に画面に出力された内容がそのまま、requirements.txtに出力され、別の仮想環境を作成して、
~~~
pip install -r requirements.txt
~~~
とすることで、必要なバージョンの必要なモジュールが一発でインストールされるといった具合です。

ところで、このpip freezeコマンドですが、モジュール名==バージョンといった期待した形式で出力されない事があります。
~~~
aiohttp @ file:///C:/ci/aiohttp_1646806572557/work
aiosignal @ file:///tmp/build/80754af9/aiosignal_1637843061372/work
alabaster @ file:///home/ktietz/src/ci/alabaster_1611921544520/work
anaconda-client @ file:///C:/ci/anaconda-client_1635342725944/work
anaconda-navigator==2.2.0
anaconda-project @ file:///tmp/build/80754af9/anaconda-project_1637161053845/work
anyio @ file:///C:/ci/anyio_1644481921011/work/dist
appdirs==1.4.4
argon2-cffi @ file:///opt/conda/conda-bld/argon2-cffi_1645000214183/work
~~~

モジュール名==バージョンとなっている項目もありますが、
モジュール名 @ file:///~~~
のように、ローカルパスが記述されているモジュールも混ざっています。

自分も全ての組み合わせを調べた訳ではないのであまり詳しくは分かりませんが、Windows上のAnacondaで作成した仮想環境で実行する時に起こるとことがどうやら多いようですが、UbuntuでAnacondaを使用しない場合にも同様のフォーマットで出力される例が報告されているようで、そう単純な問題ではないようです。

[pip freeze creates some weird path instead of the package version（英文）](https://stackoverflow.com/questions/62885911/pip-freeze-creates-some-weird-path-instead-of-the-package-version "Stack Overflow")

[pip freeze > requirements.txtで作成すると @file:ができる？](https://teratail.com/questions/272968 "teratail")

Githubのpipコマンドのissueとしても記録されていることから、必ずしもAnaconda固有のものではないようです。

[pip freeze does not show version for in-place installs #8174](https://github.com/pypa/pip/issues/8174 
 "Github")

解決方法は幾つかあるのですが、Anacondaを使用しているという点に着目する場合は、

~~~
conda list --export
~~~

というAnaconda用のコマンドを使用します（リダイレクト部分を省略しています）
このコマンドはAnacondaで作成された仮想環境からのみ実行できます。

~~~
(ExcelSync) C:\Users\yagi->conda list --export
# This file may be used to create an environment using:
# $ conda create --name <env> --file <this file>
# platform: win-64
altgraph=0.17.2=pypi_0
bzip2=1.0.8=he774522_0
ca-certificates=2022.07.19=haa95532_0
certifi=2022.6.15=py310haa95532_0
cycler=0.11.0=pypi_0
distlib=0.3.6=pypi_0
et-xmlfile=1.1.0=pypi_0
filelock=3.8.0=pypi_0
fonttools=4.37.1=pypi_0
future=0.18.2=pypi_0
・
・
・
~~~
ファイルへ出力する場合は、
~~~
conda list --export > requirements.txt
~~~
とリダイレクトしてください。

出力された内容には、バージョン番号の代わりに、「hbb2ffb3_0」や「pypi_0」などの文字列が続くところが少し気になります。
ただAnaconda同士で依存関係のあるモジュールを再現するだけであれば十分のようです。


もう１つの方法ですがこの方法が今のところ、Anaconda環境とvenv、virtualenvなどの異なる仮想環境でも同じように使用出来て、出力される内容のフォーマットも同じで、1番有力だと思われるもので、以下のコマンドになります。
~~~
pip list --format=freeze
~~~

この構文では、pip listに--format=freezeオプションをつけて実行するものです。ファイルへ出力する場合は、
~~~
pip list --format=freeze > requirements.txt
~~~
とリダイレクトしてください。


Anacondaでの実行例は以下の通りです（リダイレクト部分を省略しています）
~~~
(ExcelSync) C:\Users\yagi->pip list --format=freeze
altgraph==0.17.2
certifi==2022.6.15
cycler==0.11.0
distlib==0.3.6
et-xmlfile==1.1.0
filelock==3.8.0
fonttools==4.37.1
future==0.18.2
kiwisolver==1.4.4
lxml==4.9.1
・
・
・
~~~

また、同じコマンドをvirtualenv上で実行して出力された内容が以下の通りです（同じくリダイレクト部分は省略しています）
~~~
(excel_sync) C:\~~~~\DataSync>pip list --format=freeze
altgraph==0.17.2
cycler==0.11.0
distlib==0.3.6
et-xmlfile==1.1.0
filelock==3.8.0
fonttools==4.37.1
future==0.18.2
kiwisolver==1.4.4
lxml==4.9.1
matplotlib==3.5.3
・
・
・
~~~

他にも確認を取ってみたい環境がたくさんありますが、今までのところは、
pip list --format=freezeがあらゆる場面で均質な出力を返しており汎用性が高そうです。
また、なにか分かったら記載します。