Ubuntu Weekly Recipe

第850回UbuntuにおけるシステムPythonと⁠Pythonの仮想環境を使い分ける方法

Ubuntuにおけるシステムソフトウェアの多くがPythonに依存しています。そのためほとんどのUbuntu関連OSでは、最初からPythonがインストールされているはずです。今回はそんなUbuntuを動かす上で必要な「システムPython」と、一般的なPythonとの関係性と基本的な使い方についてまとめておきましょう。

Ubuntuにおける「システムPython」とは

UbuntuのシステムコンポーネントのいくつかはPythonに依存しています。たとえばサーバー版だけでも、パッケージ管理システムを補助するツールや、netplan.ioやufwなどのネットワーク設定ソフトウェアなどがPythonで作られています。デスクトップ版になるとさらに多くのソフトウェアがPythonに依存しているのです。

このような「Ubuntuシステム」にとって重要なPython環境を、ここでは便宜上システムPythonと呼ぶことにしましょう。

システムPythonは、Ubuntuのリリースごとに一意のバージョンを持っています。つまりあるUbuntuリリースにおいては「このバージョンのPythonが使われる」ことが決まっているのです。具体的には次のようなバージョンが採用されています。

リリース バージョン
4.10 2.3.4 Ubuntuの登場
14.04 2.7.5
16.04 2.7.12
18.04 3.6.7 Python 3のみに移行
20.04 3.8.2
22.04 3.10.6
24.04 3.12.3 Python 2の完全削除
25.04 3.13.1 開発中のリリース

バージョンについては2025年2月時点での数字です。UbuntuのシステムPythonの場合、同じリリースでもマイクロバージョン(X.Y.Zの「Z」の部分)についてはアップグレードされることがあります。

UbuntuではもともとPython 2を使っていました。その後、Python 3へと段階的に移行し、2017年10月にリリースされた17.10からデスクトップ版でもPython 2が標準ではインストールされなくなりました。それからもPython 2のパッケージ自体は存在したのですが、2024年4月の24.04までにPython 2関連パッケージはすべてインストールできないようになっています。

ちなみにリリースによっては、⁠複数のバージョンのPython」を提供していることもあります。たとえばUbuntu 22.04 LTSのシステムPythonのバージョンは3.10.6ですが、⁠python3.11」パッケージをインストールすればPython 3.11系も使用できます。ただしpython3.11をインストールしても、システムPython自体はpython3.10パッケージのままです。他のリリースでも、⁠python3」パッケージがどのPythonパッケージに依存しているかという点でシステムPythonのバージョンを確認すると良いでしょう[1]

UbuntuのパッケージリポジトリにあるPython関連パッケージは、基本的にはこの「システムPython」に合わせたバージョンのものが採用されています。つまりUbuntu開発時のワークフローはおおよそ次のようになります。

  1. リリース開発期間に合わせたバージョンのPythonパッケージがひとつないし複数用意される
  2. その中からシステムPythonのバージョンを決定する
  3. 必要に応じてシステムPythonのバージョンで動くようにPython関連パッケージを調整する
  4. 古いバージョンのPythonに依存するパッケージがなくなればそのバージョンのPython本体のパッケージは削除する

これをリリースごとに実施するのです。Ubuntu 24.04 LTSだとpythonカテゴリにあるパッケージだけでも、バイナリパッケージで5000近くありますのでそれなりに大変な作業となります。

$ apt list '~spython' 2>/dev/null | wc -l
4848

ちなみにこの移行作業(transition)は他の言語でも似たような対応が行われています。アップストリームであるDebianで行われる場合もありますし、Ubuntuのリリーススケジュールに合わせてUbuntu側だけで実施することもあります。現在予定されている移行作業は、Ubuntu Archiveチームのサイトで確認できます。

このように対応することで、UbuntuのシステムPythonとパッケージリポジトリは次のような特性を持ちます。

  • Ubuntuの特定のリリースにおいて「システムPython」は特定のPythonバージョン(メジャーバージョン+マイナーバージョン)を想定している[2]
  • Ubuntuの公式リポジトリにあるPython関連パッケージは原則としてシステムPython上でのみ動くことを想定している
  • Ubuntuの公式リポジトリにあるPython関連パッケージは、同じリポジトリ・リリースにあるPythonライブラリを使ってのみ動くことを想定している

たとえばシステムPythonである「python3」パッケージに依存するライブラリ「python3-foo」と、それを使用する「python3-bar」「baz」というパッケージがあったとします[3]。このときpython3-barやbazは、システムPythonで動くpython3-fooとの組み合わせのみを想定しているのです。

このような前提に立った時、ひとつの問題が出てきます。つまりpipなどでインストールするライブラリは、Ubuntuが提供するそれに対して優先的に使われるべきなのかという問題です。先ほどの例だと「python3-foo」がインストールされている状態で、pip install fooを実行することを考えています。グローバル環境にPythonモジュール「foo」の最新版がインストールされると、python3-barやbazはうまく動かなくなる可能性が出てくるのです。

これに対してPython側ではPEP 668を策定して、Python固有のパッケージ管理システムでインストールするソフトウェアは仮想環境内に閉じ込めるよう、ユーザーへ促す方向に舵を切りました。Ubuntuでも、23.03以降にUbuntuパッケージ版のpip3コマンドでPythonパッケージをインストールしようとすると、エラー扱いとなっています。

つまり利用者としては次のような判断をしなくてはならないのです。

  • 選択肢1:aptコマンドでPython製のソフトウェアやモジュールをインストールして使用する

    • Ubuntuのパッケージ管理システムだけで完結するため、もっとも管理が楽な仕組み
    • ただし特定の(大抵の場合は古い)バージョンしか使えないのが難点
    • Pythonのバージョンが固定化される点も注意が必要
    • 新しいソフトウェアやバージョンがどんどん登場しているジャンルだと不向き
    • 機械学習などでよくある「古いPythonでしか動作確認していない」ソフトウェアなどにも合っていない
    • 「定番」である程度機能が「安定」しているものを使う場合の選択肢になる
  • 選択肢2:自作のシンプルなPythonスクリプトを、Ubuntuのバージョンに合わせて動かす

    • 標準ライブラリしか使わないようなスクリプトなら、Ubuntuのバージョンに合わせて調整するのが一番楽
    • どうしても特定のバージョンのPythonでないと困る場合は、後述のdeadsnakes/ppaを使うという手もある
    • 規模が大きくなってきたらPythonパッケージとして、次の項目と同じ扱いにすることとなる
  • 選択肢3:Ubuntuリポジトリにないソフトウェアやモジュール、バージョンのPythonソフトウェアを動かす

    • Ubuntuのパッケージ管理システムが使えないケース
    • PEP 668の推奨に従えば、Pythonの文脈における「仮想環境」を作り、そこにPythonのやり方でインストールする
    • これにはいくつかの方法があるので、さらに選択が求められることになる
    • またPythonはちょくちょく「定番の方法」が変わるのでそこにも注意が必要

十分に安定したソフトウェアであればまずは選択肢1の検討をおすすめします。特にサーバーのような継続的にセキュリティアップデートを適用しながら運用するシステムであれば、メンテナンスのコストが大きく下がります[4]。さらに言うと、もし「リポジトリにない」ソフトウェアであれば、いっそのことDebianのPythonパッケージングチームと協力してDebianパッケージ化すれば、より多くの人が幸せになります。

ここからは「選択肢1」を採用できなかった場合に、選択肢2や3を行う上での「Ubuntuの方法」を紹介しましょう。

Ubuntuに「python」コマンドは存在しない

少し話がそれますが、最近のUbuntuにPythonシステムはインストールされているものの、⁠python」コマンドは存在しません。Pythonのインタープリターのコマンド名はあくまで「python3」です。

$ python
Command 'python' not found, did you mean:
  command 'python3' from deb python3
  command 'python' from deb python-is-python3

Ubuntuにおける「python(/usr/bin/python⁠⁠」は伝統的に「Python 2のインタープリター」を意味していました。これはPython 2が削除された現在も同じです。Python 3に移行する際、⁠/usr/bin/python」は果たして「Python 3」にスイッチすべきか議論された結果として、⁠Python 2のまま」という判断がくだされました。

もし何らかの理由で「/usr/bin/python」がPython 3であって欲しい場合は、次のパッケージをインストールしておいてください。

$ sudo apt install python-is-python3

古いリリースのPythonをお手軽に使いたい

前述したとおりUbuntuのシステムPythonは、特定のバージョンに固定化されています。しかしながら自前のスクリプトや特定のPythonソフトウェアを動かすために、より新しいもしくは古いバージョンのPythonが必要になることはよくあります。

複数のバージョンのPythonを管理する場合、Python的にはpyenvやuvを使うのが一般的です。ただしこの場合はpyenvやuvが指定したディレクトリに環境が保存され、システムグローバルにそのバージョンが使えるとは限りません。もうすこしお手軽に異なるバージョンのPythonをインストールする方法としてよく使われるのが、deadsnakesが提供するdeadsnakes/ppaです。

このPPAを導入するとaptコマンドで、いくつかのバージョンのPythonをインストールできます。

$ sudo add-apt-repository ppa:deadsnakes/ppa
$ sudo apt -U install -y python3.9
$ python3.9 --version
Python 3.9.21

ただしすべてのPythonのバージョンをサポートしているわけではなく、Ubuntuの個々のリリースでビルドできるものに限られています。2025年2月時点では次のようなバージョンが提供されていました。

  • Ubuntu 20.04 LTS: Python 3.5 - 3.7, 3.9 - 3.13
  • Ubuntu 22.04 LTS: Python 3.7 - 3.9, 3.11 - 3.13
  • Ubuntu 24.04 LTS: Python 3.7 - 3.11, 3.13

間が抜けているのはUbuntu本体でサポートしているバージョンです。またアルファ版である3.14のパッケージも存在しています。

Pythonインタープリターのコマンド名は「pythonX.Y」となります。また、Python本体とは別に、次のようなパッケージも提供されます。

  • pythonX.Y-dev
  • pythonX.Y-venv
  • pythonX.Y-distutils
  • pythonX.Y-lib2to3
  • pythonX.Y-gdbm
  • pythonX.Y-tk

言い方を変えると、これ以外についてはdeadsnakes/ppaからは提供されません。必要に応じてpip等でインストールすることになります。

pipの代替としてのpipx

Python製のあるソフトウェアをインストールしたいだけであれば、pipではなくpipxがおすすめです。

pipxはまずvenvを用いて、ユーザーのホームディレクトリ内部に仮想環境を構築します。さらにその中に必要なモジュールを一通りインストールし、そのコマンドのシンボリックリンクを~/.local/bin/に作成してくれます。pipxを実行したユーザーは、システムにインストールしたときと同じような形でそのPythonソフトウェアを利用できるのです。

$ sudo apt install pipx
$ pipx install cowsay
  installed package cowsay 6.1, installed using Python 3.12.3
  These apps are now globally available
    - cowsay
⚠️  Note: '/home/ubuntu/.local/bin' is not on your PATH environment variable. These apps will not be globally accessible until your PATH is updated. Run `pipx ensurepath` to automatically add it, or
    manually modify your PATH in your shell's config file (i.e. ~/.bashrc).
done! ✨ 🌟 ✨

インストールされたコマンドは~/.local/binにシンボリックリンクが作られますが、初期状態だとコマンドの検索パスが設定されていません。ただ、Ubuntuの~/.profile~/.local/binが存在すれば検索パスを設定してくれるので、一度ログアウトすると良いでしょう。

$ ls -l ~/.local/bin/
total 4
lrwxrwxrwx 1 ubuntu ubuntu 54 Feb 11 13:02 cowsay -> /home/ubuntu/.local/share/pipx/venvs/cowsay/bin/cowsay

$ cowsay
Command 'cowsay' not found, but can be installed with:
sudo apt install cowsay

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin

(一度ログインし直す)

$ cowsay -c tux -t "Hello"
  _____
| Hello |
  =====
          \
           \
            \
             .--.
            |o_o |
            |:_/ |
           //   \ \
          (|     | )
         /'\_   _/`\
         \___)=(___/

ちなみにインストール時に--python Pythonコマンドのパスを指定してあげれば、インストール済みの任意のバージョンのPythonインタープリターを指定できます。

pipとvenvで仮想環境を構築する

pipxは単一のPythonソフトウェアとその依存関係をインストールするのに適していますが、pip等を使ってライブラリをインストールする場合は引き続きpipコマンドが必要です。その場合は、venv等と合わせて使うことになるでしょう。実際にpipxも内部的には似たようなことをやっています。

$ sudo apt install python3-pip python3-venv

仮想環境を作成し有効化する
$ python3 -m venv foo
$ source foo/bin/activate

cowsayを仮想環境内にインストールする
(foo) $ pip install cowsay
Collecting cowsay
  Downloading cowsay-6.1-py3-none-any.whl.metadata (5.6 kB)
Downloading cowsay-6.1-py3-none-any.whl (25 kB)
Installing collected packages: cowsay
Successfully installed cowsay-6.1
(foo) $ command -v cowsay
/home/ubuntu/foo/bin/cowsay

仮想環境を無効化するとcowsayが見えなくなる
(foo) $ deactivate
$ command -v cowsay
(cosayが見えなくなる)

Python関連ツールをしっかり使う

ここまでは「Ubuntuのリポジトリにあるツール」を使って、環境を構築する方法を紹介しました。しかしながらPythonのツールは日進月歩で変化しています。カジュアルに使うだけであれば、pipx/pip/venvで事足りるでしょうが、より効率的な方法・今風の方法を模索したいのであれば、Ubuntuリポジトリにあるものだけでは足りないでしょう。

ここではその中からpyenvとuvを紹介しましょう。

pyenv

最初のpyenv⁠、任意のバージョンのPythonをインストールしその環境を構築するツールです。前述のdeadsnakes/ppaの汎用版だと思っておけば良いでしょう。インストール方法自体はそこまで難しくないのですが、Pythonをビルドする都合で開発系のパッケージをインストールしなくてはなりません。

$ sudo apt install build-essential libssl-dev zlib1g-dev \
    libbz2-dev libreadline-dev libsqlite3-dev curl git \
    libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev \
    libffi-dev liblzma-dev
$ curl -fsSL https://pyenv.run | bash
(中略)
# Load pyenv automatically by appending
# the following to
# ~/.bash_profile if it exists, otherwise ~/.profile (for login shells)
# and ~/.bashrc (for interactive shells) :

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"

# Restart your shell for the changes to take effect.

# Load pyenv-virtualenv automatically by adding
# the following to ~/.bashrc:

eval "$(pyenv virtualenv-init -)"

上記のスクリプトは~/.pyenv以下にpyenvをgit cloneしているだけです。~/.pyenv/binに検索パスを設定する手順が実行結果の末尾に書かれていますので、以下の三行を~/.profileの末尾に追加しましょう。

export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init - bash)"

一度ログインしなおせば、pyenvコマンドを使えるようになります。

$ pyenv --version
pyenv 2.5.2

「pyenv list」でインストールできるPython環境一覧が表示されます。たとえばPython 3.9.11をインストールするなら次のように実行します。

$ pyenv install 3.9.21
Downloading Python-3.9.21.tar.xz...
-> https://www.python.org/ftp/python/3.9.21/Python-3.9.21.tar.xz
Installing Python-3.9.21...
Installed Python-3.9.21 to /home/ubuntu/.pyenv/versions/3.9.21
$ pyenv versions
* system (set by /home/ubuntu/.pyenv/version)
  3.9.21
$ command -v python3.9
/home/ubuntu/.pyenv/shims/python3.9

使用するバージョンは「pyenv global version」「pyenv local version」で指定できます。globalはどのディレクトリで「python3」を実行しても指定したバージョンになり、localは設定したディレクトリ以下でのみ指定したバージョンになります。

$ mkdir test && cd $_
$ pyenv local 3.9
$ pyenv versions
  system
* 3.9.21 (set by /home/ubuntu/.python-version)
$ python3 --version
Python 3.9.21
$ cat .python-version
3.9
$ cd ..
$ python3 --version
Python 3.12.3

あとは、これとpip/venvを組み合わせれば任意のバージョンのPython環境を構築できるでしょう。

uv

最近はuvと呼ばれるツールも人気です。これはRust製のPython環境構築ツールで、ここまで説明したpip/venv/pyenvの機能がだいたいこれひとつでまかなえます。

ただしUbuntu/Debianのパッケージリポジトリにはuvはまだ用意されていません。公式のインストールスクリプトを使ってインストールすることになります。

$ curl -LsSf https://astral.sh/uv/install.sh | sh
downloading uv 0.5.30 x86_64-unknown-linux-gnu
no checksums to verify
installing to /home/ubuntu/.local/bin
  uv
  uvx
everything's installed!

To add $HOME/.local/bin to your PATH, either restart your shell or run:

    source $HOME/.local/bin/env (sh, bash, zsh)
    source $HOME/.local/bin/env.fish (fish)
WARNING: The following commands are shadowed by other commands in your PATH: uv uvx

$ ls .local/bin/uv
.local/bin/uv
$ uv --version
uv 0.5.30

uv自体はglibcにしか依存しないバイナリなので、1個のファイルを~/.local/bin以下にダウンロード&インストールするだけです。pipxのときと同じようにインストール後はログインしなおして検索パスに~/.local/binが含まれるようにしましょう。

具体的な使い方については、gihyo.jpで連載中の「Python Monthly Report」の記事が参考になります。

Anaconda

データサイエンスや機械学習でよく使われるAnacondaも人気のPythonディストリビューションです。ソフトウェアによってはcondaコマンドによるインストールを要求されることもあるでしょう。

インストール方法は他と同じくスクリプトをダウンロードして実行になります。ただしPythonのパッケージ一式をダウンロードする都合上サイズが大きくなりがちな点に注意してください。コンパクトなバージョンもあり、用途に応じて使い分けることになります。

$ sudo apt install curl make
$ curl -LO https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh
$ bash Anaconda3-2024.06-1-Linux-x86_64.sh
(snip)
Do you accept the license terms? [yes|no]
>>> yes
あとはEnterでOK
$ source ~/anaconda3/etc/profile.d/conda.sh
$ conda --version
conda 24.5.0

~/anaconda3/にいろいろとインストールされます。

condaもpip/venv/pyenv/uvと同じようなことが実現できます。ただし使用する環境や組み合わせによっては有償ライセンスを必要とする点に注意しましょう。

Ubuntuが登場してから20年以上経ち、いつの間にやらPythonは技術的な面だけでなく、社会的な面でも重要な存在となってしまいました。これからも様々な人が多種多様な目的でPythonを使うことになるでしょう。もしUbuntu上でPythonを使いたい場合は、今回紹介したようなことを念頭に置いておくと変な問題に絡まれなくて済むはずです。

おすすめ記事

記事・ニュース一覧