[python初心者] 仮想環境venvのことを調べました
venvとは
pythonで仮想環境を作るためのモジュール
Python3.3以降で標準ライブラリの一部になった
なぜ仮想環境必要か
仮想環境は、プロジェクトごとに異なるパッケージやパッケージバージョンを管理するために使用される。
システム全体のPythonインストールを変更せずに、プロジェクト固有の依存関係を維持することができる。
javascript/node.jsのpackage.jsonがあって、インストールして関連パッケージがnode_modulesに格納されると同じイメージ
仮想環境基本コマンド
前提としてPythonがシステムにインストールされていること
つまりpython
またはpython3
コマンドを実行できること
仮想環境の作成
現在ディレクトリ位置から仮想環境作成する
python -m venv venv
基本はプロジェクトリポジトリー配下で作成
フロントエンド・バックエンドが同じリポジトリーにある場合はcd backendなどしてバックエンドディレクトリ配下に移動してから
-m
は、モジュールをコマンドラインから直接実行できるようにするためのオプション
1つ目のvenv
はモジュールの名前を指し
2つ目のvenv
は仮想環境の名前で、任意の名前を指定できるが、ほとんどの記事でみかけるのはそのままvenvの名前で仮想環境作っているようです
例えば
python -m venv myenv
とか任意の名前でもオッケーは仮想環境の名前ですが、任意の名前に置き換えることができます。
仮想環境のアクティベート
dockerのコンテナーを立ち上げてないと使えないように、venv仮想環境も使うのにアクティベートが必要
アクティベートすると、その仮想環境内でインストールされているPythonとパッケージが使用されるようになる
- Windows:
venv\Scripts\activate
- macOS と Linux:
source venv/bin/activate
仮想環境でのパッケージ管理
仮想環境がアクティベートされたら、pip
を使用してパッケージをインストール、アンインストール、またはアップグレードできる
たとえば、requests
パッケージをインストールする
pip install requests
仮想環境の非アクティベート
アクティベートされている仮想環境から出るためのコマンド
deactivate
仮想環境出たら、またシステムのグローバルPythonインストールに戻っていることになる
仮想環境の削除
あまりやらないかもだが、仮想環境がアクティベートでないときに、ディレクトリを削除すればそれだけで済む話
node_modulesディレクトリまるごと削除してpackage.jsonからインストールし直すみたいなイメージで
venvディレクトリをまるごと削除すれば仮想環境は削除される
さてpythonの仮想環境をインストールしなおそうと思うと、package.jsonに相当するrequirements.txtが必要
requirements.txtのこと
必要なパッケージを記録して再利用できる
仮想環境を作ってアクティベートするだけでは、pythonの標準ライブラリしか使えないので、仮想環境内でpip installして都度必要なパッケージをインストールする
だけどpip installしただけでは、その仮想環境内にどんなパッケージがインストールしているかわからない
インストール済みのパッケージを記述するのはrequirements.txtのことで
アクティベートの状態で
pip freeze > requirements.txt
でrequirements.txtが作られる
requirements.txtには、現在の仮想環境にインストールされている全てのパッケージと、それらの具体的なバージョンが記載されている
venvを削除してインストールしなおすときは、ほかの他の開発者が同じ環境を再現するとき
pip install -r requirements.txt
でパッケージがインストールできる
仮想環境作りたてのとき
python -m venv venv
source myenv/bin/activate
pip freeze > requirements.txt
これは空のrequirements.txtが作られるだけ
まだ何もパッケージインストールしてないので
そこからpip installしても、requirements.txtが空のまま
pip installしただけでは自動で記録されない
毎回手動でpip freeze > requirements.txt
する必要がある
シェルスクリプトでpip install
とpip freeze > requirements.txt
を一緒に実行するようにする
touch pipf.sh
#!/bin/bash
pip install "$@"
pip freeze > requirements.txt
シェルスクリプトに実行権限与える
chmod +x pip_install.sh
それでインストールするときは
./pipf.sh hogehoge
でpip installとpip freezeを両方やってくれる
参考記事
仮想環境外でpip installやってしまっていた
仮想環境をアクティベートせずにpip install
コマンドを実行した場合、パッケージはシステムのグローバルPython環境にインストールされてしまう
これは複数プロジェクトのパッケージ依存関係に競合が発生したり、プロジェクトの環境の再現が難しくしたりと、多くの不都合をきたすので基本やらない
仮想環境を使うのが基本
だけどvenvのことわからないままpip installをすでにいろいろやっちゃったのでちょっと整理しようと
グローバルでインストールされているパッケージを確認
仮想環境がアクティベートされていない状態で
pip list
インストールされているパッケージの名前とバージョンのリストが表示される
リストには、Pythonの標準ライブラリに含まれない、pipを使用してインストールされたパッケージが含まれる
システムに複数python環境があると、それぞれのリストがある
例えば
pip3 list
pythonをインストールしただけの状態では、pip, setuptools, wheelなどの基本パッケージしかないようですが、自分のローカル環境でpip listやってみたら長いリストでてきた。。。
うん。。。何年もわからないままpip installやっちゃってるもんね。。。
グローバルにインストールすべきじゃないものを削除
全部削除して動かなくなったのも大変なので、とりあえず現状のリストを保存する
pip list --format=freeze > installed_packages.txt
とりあえずこれでinstalled_packages.txtに保存されるので、requirements.txtと全く同じで最悪インストールしなおせばいい
installed_packages.txtの確認して、必要なパッケージ以外全部アンイストールする
grep -vE "pip|setuptools" installed_packages.txt | xargs pip uninstall -y
必要かどうかの判断は難しくて、全部削除するのが怖い、という場合は、パッケージごとの依存関係は調べられるので、絶対グローバルじゃなくていいものを手動で削除する
pip show <package-name>
で依存パッケージしらべられる
例えばgspreadというパッケージは特定のプロジェクトしか使わないと分かっているので
% pip show gspread
Name: gspread
Version: 5.12.3
Summary: Google Spreadsheets Python API
Home-page:
Author:
Author-email: Anton Burnashev <fuss.here@gmail.com>
License:
Location: /Users/hogehoge/.anyenv/envs/pyenv/versions/3.11.2/lib/python3.11/site-packages
Requires: google-auth, google-auth-oauthlib
Required-by:
とgspreadと一緒にgoogle-auth, google-auth-oauthlibも削除できるとわかる
万一グローバルパッケージの削除でトラブったら
pip install -r installed_packages.txt
でインストールし戻す
pip list --format=freeze
とpip freeze
違い
作成されたrequirements.txtとinstalled_packages.txtをみる限りほとんど一緒
実際ほとんど一緒
pip freeze
: 依存関係の記録や共有に特化している
pip list --format=freeze
: より汎用的な pip list コマンドの出力形式の一つ
pip list --format=freeze > installed_packages.txt
pip list コマンドはインストールされているパッケージをリストアップ
--format=freeze オプションは出力フォーマットを指定して、結果pip freeze と同様の出力を生成している
作ったinstalled_packages.txtは、作成される時点のPython環境(グローバルまたは仮想環境)にインストールされている全てのパッケージのスナップショットで、デバッグや環境の完全な復元、ドキュメント化の目的で使用される
pip freeze > requirements.txt
pip freeze コマンドは、現在の環境にインストールされているパッケージとそのバージョンを パッケージ名==バージョン の形式で出力
もっぱらプロジェクトの依存関係を requirements.txt ファイルに保存するためのコマンド
pip freezeで作ったrequirements.txtは、特定のプロジェクトの依存関係を定義するために使用され、常は、プロジェクトの実行に絶対に必要なパッケージのみを含む。
つまり開発者が意図的に選択したものをリストアップしていることになります
まあ、ほとんど一緒で、なんならファイル名も任意でよかった
pip install -r hogehoge.txt
コマンドはファイル名を引数で渡すので、内容が正しい形式であればどのような名前でも動く
名前は何でもよかったけど、慣例的にrequirements.txt
を使っていて、Pythonプロジェクトにおける依存関係リストのための業界標準のようなもの
プロジェクトが複数の依存関係セットを持っている場合は、dev-requirements.txtやprod-requirements.txtなど、目的に応じて名前を変更することができる
installed_packages.txt
はなんの目的かわからなくなるので、例えば、snapshot-2024-02-03.txtのように特定の日付を含めることで、いつこのスナップショットがわかるようにしたり
そもそもPythonの標準ライブラリに何が入ってる?
Pythonの公式ドキュメント参照
例えばpython 3.12.1の標準ライブラリは
例えばこんなものが入ったりしてます
-
math
: 数学関数 -
datetime
: 日付と時刻の操作 -
os
: オペレーティングシステムとのインタラクション -
sys
: Pythonインタプリタとその環境にアクセスするための関数と変数を提供 -
re
: 正規表現による文字列処理 -
json
: JSONデータの読み書き -
http
: HTTPと関連プロトコルを扱うためのモジュール群 -
unittest
: ユニットテストのフレームワーク
と、標準ライブラリでも大量のパッケージが入っている
公式ドキュメントは標準ライブラリの各モジュールの使い方、関数、クラス、例外などについて詳細にかかれてある
まだまだ勉強するものが大量にある
Discussion