はじめに
Pythonには多くのパッケージがありますね。そのパッケージを管理するためにpipを使っている人も多いのではないでしょうか。pipは簡単にパッケージを導入できるシステムですが、パッケージ同士の依存関係がわからない!なんてことに直面したことはありませんか?(私はあります。)
インストール済みのパッケージなら、ターミナルから調べることができますが、インストールしてあるかどうかに関わらずうまく調べる方法はないものか?と思い、シェルコマンドを作ってみました。
環境
- MacBook Pro 2017
- macOS Big Sur 11.6
- Python 3.10.0
- Z Shell 5.8
インストール済みのパッケージの依存関係を調べる
復習にはなりますが、インストール済みのパッケージの依存関係は、ターミナルから次のように調べることができます。
$ pip3 show <パッケージ名>
例として、numpyについて調べてみると、以下のように出力されました。
$ pip3 show numpy
Name: numpy
Version: 1.21.3
Summary: NumPy is the fundamental package for array computing with Python.
Home-page: https://www.numpy.org
Author: Travis E. Oliphant et al.
Author-email:
License: BSD
Location: /usr/local/lib/python3.10/site-packages
Requires:
Required-by: altair, matplotlib, opencv-python, pandas
pip3 show
コマンドでは、パッケージの名前やバージョンの他、保存されている場所や依存関係がわかります。numpyの場合、インストール済みのパッケージの中に依存しているもの(Requires)はなく、依存されているもの(Required-by)として、altair, matplotlib, opencv-python, pandas
があるようです。ではインストールしていないパッケージを指定してみるとどうなるのでしょうか。
$ pip3 show Pyarrow
WARNING: Package(s) not found: Pyarrow
このように"not found"になってしまうようです。
未インストールパッケージの依存関係を調べる
以下のQiita記事を参考にさせていただきました。
手順1: 動作をスクリプトとして書き出す
とりあえず、処理を書き出します。おそらくどの言語を使っても良いとは思いますが、pipがPython関連なので~~(シェルの文法がよくわからないので)~~、私はPythonで記述しました。
そして完成したコードがこちら。
import requests
import sys
from pprint import pprint
def pipreq(s_1,i_1):
package = s_1
version = i_1
if version != "none":
url = f'https://pypi.org/pypi/{package}/{version}/json'
else:
url = f'https://pypi.org/pypi/{package}/json'
json = requests.get(url).json()
pprint(json['info']['requires_dist'])
if __name__ == "__main__":
print("調べたいモジュールの名前とバージョンを空白区切りで入力してください。\
\nバージョンを指定しないときはnoneと入力してください。\n")
s_1, i_1 = input().split()
pipreq(s_1, i_1)
標準入力としてパッケージ名とバージョン名を受け取り、pypiのサイト上のjsonから探し出すようになっています。そして、依存関係にあるパッケージ名を出力するようになっています。
実行例はこちら。
$ python3 pip_requirements_search.py
調べたいモジュールの名前とバージョンを空白区切りで入力してください。
バージョンを指定しないときはnoneと入力してください。
pandas none
['python-dateutil (>=2.7.3)',
'pytz (>=2017.3)',
'numpy (>=1.17.3) ; platform_machine != "aarch64" and platform_machine != '
'"arm64" and python_version < "3.10"',
'numpy (>=1.19.2) ; platform_machine == "aarch64" and python_version < "3.10"',
'numpy (>=1.20.0) ; platform_machine == "arm64" and python_version < "3.10"',
'numpy (>=1.21.0) ; python_version >= "3.10"',
"hypothesis (>=3.58) ; extra == 'test'",
"pytest (>=6.0) ; extra == 'test'",
"pytest-xdist ; extra == 'test'"]
このように、依存関係のみが出力されるスクリプトを書くことができました。
手順2: シェルのエイリアスとして設定する
手順1だけでも動作に問題はないのですが、いちいちファイルを指定して実行するのが面倒…ということで、シェルのエイリアスにしました。順を追って説明します。
まず、シェルの設定ファイルを開きます。私の場合はzsh
を使っているので、.zshrc
を開きます。エディタはvim
ですが、宗教上の理由がある人はemacs
などでも問題ないです。
$ vi ~/.zshrc
次に、以下のようにスクリプトファイルのパスを記述し、エイリアスにします。コマンドの名前は自分が覚えられるものにしましょう。わかりやすくホームディレクトリ直下に配置していますが、好きな場所で良いでしょう。
alias prs="python3 /Users/hogehoge/pip_requirements_search.py"
作業内容を保存したあと、反映して設定完了です。(←この工程を忘れると "command not found" になります。)
$ source ~/.zshrc
手順3: 権限を付与する
実行権限がないと、"permission denied" というエラーが出てしまいます。そのため、権限を付与しましょう。ターミナルで以下のように入力します。sudo
なので、パスワードが求められます。ログインパスワードを入力しましょう。
$ sudo chmod 755 ~/pip_requirements_search.py
おわりに
よく使う処理は、このようにシェルのエイリアスにしておくと結構便利ですね。