Pythonの依存関係管理をやさしく解説
Lucian Irsigler
2021年9月14日
0 分で読めますPythonは「シンプル」な言語とされており、使いやすく、Webスクレイピングや自動化、大規模なWebアプリケーションの構築、さらにはデータサイエンスまで、さまざまなタスクを実行するスクリプトを簡単に作成できます。しかし、Pythonの依存関係の管理方法は他の言語とは大きく異なり、環境の構築方法やパッケージマネージャーの選択肢が数多くあることも、混乱に拍車をかけています。この記事では、Pythonの依存関係を管理するさまざまな方法を紹介し、依存関係のセキュリティについても簡単に解説します。
インタープリター型言語としてのPython
インタープリター型言語とは、スクリプトが機械語や実行ファイルに変換されない言語のことです。スクリプトは別のプログラム、この場合はPythonインタープリターを介して実行されます。
次のようなシンプルなPythonスクリプトを書いたとします。
そして、次のように実行します。
すると、次のように出力されます。
このコードを実行したフォルダーに、.exeのような実行ファイルがないことに気づきましたか?Pythonの実行ファイルは、事前にではなく、実行時にファイルをコンパイルして実行するためです。
実際には、Pythonコードを実行する.exeファイルがあります。Main.pyはその.exeに渡され、実行されます。この.exeファイルは、環境のパスから利用できる、コンパイル済みのPythonインタープリターです。

Pythonにおける依存関係とは
Pythonにおける依存関係は、他の言語と同じく、インポートしたソースコードを実行するために必要なコードライブラリです。
たとえば、PostgreSQLデータベースを操作したい場合、選択肢は2つあります。すべての関数を自分で書くか、クエリやその他の必要な機能を備えたパッケージpostgresをインストールします。
では、PostgreSQLに関連するパッケージはどうやってインストールすればよいでしょうか?
どの言語でも、依存関係の管理では、パッケージが適切にメンテナンスされ、セキュリティ上の問題がないことを確認するための事前調査が重要です。パッケージの全体的な状態を確認する方法の1つが、Snyk Advisorの利用です。

Snyk Advisorでは、PyPIやnpmなど、さまざまなエコシステムのライブラリについて、パッケージの状態を検索できます。Dockerのベースイメージについても、全体的な統計、人気度、利用可能なタグなどの有用な情報を確認できます。
PostgreSQL関連のプロジェクトに戻り、postgresのパッケージの状態が許容範囲内か確認してみましょう。

postgresパッケージのスコアは100点中56点と、あまり高くないようです。人気も高くなく、週あたりのダウンロード数は約1万件です。また、最終リリースは2年前で、メンテナンスが不十分である可能性があります。
ページを下にスクロールしてセキュリティとコミュニティのセクションを見ると、気になる点として、最新パッケージ(2019年10月19日リリースのバージョン3.0.0)のライセンスリスクが挙げられています。詳しく確認する必要がありそうです。

このパッケージを使う場合、先ほどのpip installコマンドを実行すると、システムからpostgresパッケージを利用できるようになります。
プロジェクトにインポートするには、次のようにします。
これで、Pythonの依存関係がいかに厄介になり得るかがわかるでしょう。このスクリプトを、Pythonをインストールしていない友人に渡して実行してもらうと、エラーが発生します。
なぜエラーになるのでしょうか?
まず、友人の環境にPythonがインストールされている必要があります。次に、プロジェクトが依存する必要なパッケージ、この場合はpostgresが必要です。
さらに、スクリプトを実行するには、Python環境に必要なモジュールがすべてそろっている必要があります。特定のライブラリやソースコードが不足している場合、他の言語でも同様の問題が起こります。
つまり、Pythonプロジェクトを友人と共有するには、次の2つが必要です。
Pythonの実行に必要なすべてのファイル
postgresパッケージ
Pythonの依存関係管理
Pythonプロジェクトを誰かと共有するときは、requirements.txtというファイルを含める必要があります。pipコマンドを使うと、プロジェクトで必要な依存関係だけをインストールできます。
単にpipではなくpip3を使うのは、誤ったバージョンをインストールしないためです。pipは、最初にインストールしたPythonのバージョンを指します。たとえば、最初にPython 2をインストールした場合、pipコマンドはpip2を指し、Python 2のパッケージをインストールします。
つまり、pip3と指定することで、Python 3のパッケージをインストールするよう明示できます。
コンピューターにPython 2がインストールされていない場合は、この点を心配する必要はありません。
コンソールで次のコマンドを実行すると、pipコマンドがどのpip(pip2またはpip3)を使うか確認できます。
このコマンドは、プロジェクトのインストールに必要な依存関係をすべて記述したrequirements.txtを読み込み、ファイルに記載されたパッケージをインストールします。
次のコマンドを実行したときに、パッケージが実際にインストールされるようにするには、
このパッケージマニフェストファイルを作成する必要があります。
このファイルに記載するパッケージは、次の形式で指定します。
<Package name> <Higher/equal to> <some version>
例:
比較演算子はバージョンの確認に使われます。pipパッケージマネージャーが、プロジェクトに適したバージョンをインストールするためのものです。バージョン指定がなければ、最新バージョンがインストールされます。
これで、プロジェクトのソースコードを友人と共有するときに、プロジェクトに含めたrequirements.txtファイルを使ってpip3コマンドを実行するよう伝えれば、プロジェクトの実行に必要なオープンソースの依存関係をインストールしてもらえます。
Pythonの依存関係マネージャーとは?
先ほど紹介したパッケージマニフェストファイル(requirements.txt)のほかにも、Pythonプロジェクトの依存関係を簡単にメンテナンス、管理できるパッケージマネージャーがあります。インストールして使えるツールをいくつか紹介します。
Poetry
Poetryを使うと、プロジェクトの依存関係を記録したロックファイルを作成できます。パッケージをインストールすると、ロックファイルも自動的にインストールされます。ロックファイルの利点は、プロジェクトに必要な依存関係を簡単に更新できることです。
Poetryはコマンドラインツールとして動作します。たとえば、次のようなコマンドを使います。
これらのコマンドを使えば、ロックファイル内の依存関係の追跡や追加が簡単になり、その後PyPIパッケージにも追加できます。
--treeフラグを使うと、プロジェクトの依存関係をツリー形式で表示することもできます。
Poetryを使えば、依存関係を簡単に管理、追加できます。
pyenv
pyenvは、異なるバージョンのPythonを切り替えられるシンプルなツールです。依存関係が以前のバージョンのPythonで問題なく動作するか確認できます。主な用途がバージョンの切り替えであるため、Poetryなど他の依存関係マネージャーが備える機能はありません。
ただし、パッケージが以前のバージョンのPythonで動作するか確認するツールが必要なら、pyenvが役立ちます。
Setuptools
これもパッケージ管理を支援するツールです。Poetryのようなツールより多少手間はかかりますが、必要なことはきちんとこなせます。
名前のとおり、Setuptoolsはユーザーがパッケージを使い始めるための準備を支援します。つまり、スクリプトの実行に必要なパッケージをそろえるためのツールです。
Setuptoolsを使うには、pyproject.tomlファイルとsetup.py/setup.cfgファイルの2つを作成します。
.tomlファイルには、パッケージ情報の指定にSetuptoolsを使うことをPythonに伝えるため、次のコードを記述します。
次に、setup.py/setup.cfgファイルに、次のような内容を記述します。
次に、PyPA buildのようなビルダーが必要です。プロジェクトは.gzファイルにビルドされ、配布できる状態になります。
Setuptoolsでは手作業が増えますが、パッケージ管理の効率が高く、ユーザーがスクリプトの実行に必要なパッケージをすべてそろえられるようにします。
ここで紹介した3つの依存関係マネージャーは、特に人気のある選択肢です。それぞれに長所と短所がありますが、どれを選んでも、Pythonの依存関係管理を簡素化し、厄介な作業を効率よく解消できます。

さらに、Snyk CLIでは、脆弱性につながる依存関係の経路と、新しいセキュリティ修正を含むバージョンへのアップグレードによる修正方法を確認できます。
まとめ
オープンソースライブラリの脆弱性以外にも、セキュリティ上の懸念はあります。たとえば、Pythonアプリケーションに含まれる安全でないコードや、Pythonアプリケーションをまとめるコンテナの安全性などです。Daniel Bermanによる安全なPython開発のためのSnyk入門では、こうした内容を詳しく解説しています。この記事の次に読む記事としておすすめです。
Pythonの依存関係管理とセキュリティについて、参考になったでしょうか。Pythonのセキュリティについてもっと知りたい方は、こちらもご覧ください。
Capture the Flagを始めよう
オンデマンドのバーチャル入門ワークショップを見て、Capture the Flagの課題の解き方を学びましょう。
Lucian Irsiglerは、人生の複雑さを愛する情熱的なプログラマーです。
