RHEL7やCentOS 7、Amazon Linux 2でPython 3を使う

# 1. はじめに
RHEL7系のディストリビューションでは、デフォルトインストールされているPythonのバージョンは2.7となっている。そのため、3.x系を使用するには別途インストールする必要がある。

しかし、3.x系を使用する方法は複数あり、Python自身の構成方法も複数ある。複雑な状況になっているので、全体を俯瞰すると共に手順を説明する。


### 1-1. 対象環境

* Red Hat Enterprise Linux 7
* CentOS 7 / Oracle Linux 7 / Amazon Linux 2などのRHEL7系ディストリビューション

※RHEL8系でPythonを使用する方法は以下の記事を参考にしてほしい。

* [RHEL8系ディストリビューションでPython 3を使う](https://qiita.com/yamada-hakase/items/ed38a66ac10cf9cfe07e)

### 1-2. 参考情報

* [Python 3 support on Red Hat Enterprise Linux (RHEL) 7](https://access.redhat.com/solutions/2353081) ※要RHアカウント
* [Red Hat Software Collections - Release Notes - Chapter 2. Installation](https://access.redhat.com/documentation/ja-jp/red_hat_software_collections/3/html/3.6_release_notes/chap-installation)
* [Software Collections](https://www.softwarecollections.org/en/)
* [How to use Red Hat Software Collections (RHSCL) or Red Hat Developer Toolset (DTS)?](https://access.redhat.com/solutions/472793)

# 2. Python 3を使用する方法

RHEL7系ディストリビューションでPython 3を使用するには以下の選択肢がある。デフォルトでインストールされているのは2.7だ。

| No | Repository| Version |
|:-:|:--|:-:|
| 参考  | 標準リポジトリ（python）  | 2.7  |
| 1  | 標準リポジトリ（python3）  | 3.6  |
| 2  | 標準リポジトリ（python3）Amazon Linux 2のみ  | 3.7  |
| 3 | Software Collections（Amazon Linux 2以外）  | 3.5-3.8  |
| 4 | Amazon Linux 2のExtras library | 3.8  |
| 5  | EPELリポジトリ | 3.4-3.7  |
| 6  | ソースからビルド  | なんでも |

<font color="blue">この中で、Python 3を使用する標準的な方法は「1.標準リポジトリ（python3）」である。</font>ただし、Python 3.8を使いたいときは、3もしくは4、6の方法を選択する必要がある。

<font color="red">注：上記の表は2021/4時点のものだ。Software CollectionsやExtras libraryでは、今後Python 3.9などが公開される可能性もある。</font>

今回は、以下のそれぞれについて説明する。

* 標準リポジトリからPython 3をインストールする
* venvによるPython仮想環境
* Software CollectionsからPython 3.8をインストールする
* Amazon Linux 2のExtras libraryからPython 3.8をインストールする

※[IUS Community Project](https://repo.ius.io/7/x86_64/packages/)でもPython 3.6を提供しているが、2019年8月以降は標準リポジトリに含まれている。そのため標準リポジトリが推奨である。

# 3. Python 3をインストールする

標準リポジトリからPython 3.6をインストールする方法を説明する。ただし、Amazon Linux 2では3.7がインストールされる。

1. デフォルトでインストールされているのは2.7.5だ。

```shell-session
$ python -V
Python 2.7.5
```

2.python3は標準リポジトリに含まれている。

```shell-session
$ yum list python3
Available Packages
python3.i686                         3.6.8-18.el7                        updates
python3.x86_64                       3.6.8-18.el7                        updates
```

3.Python 3をインストールする。

```shell-session
# yum install python3 -y
```

4.バージョンを確認すると`2.7.5`のままだ。

```shell-session
$ python -V
Python 2.7.5
```

5.理由は、次のように`python3`というコマンドだからだ。

```shell-session
$ python3 -V
Python 3.6.8
```

6.python3やpipのシンボリックリンクを確認すると以下のようになっている。出力結果からわかることは次の3点である。

* Python2を使うときは`python`もしくは`python2.6`を起動する
* Python3を使うときは`python3`もしくは`python3.6`を起動する
* Python3用に`pip3`がインストールされている

```shell-session
$ ls -l /usr/bin/py*
-rwxr-xr-x. 1 root root    78 Nov 16 22:23 /usr/bin/pydoc
lrwxrwxrwx. 1 root root     8 Apr 12 03:30 /usr/bin/pydoc3 -> pydoc3.6
-rwxr-xr-x. 1 root root    78 Nov 16 16:57 /usr/bin/pydoc3.6
lrwxrwxrwx. 1 root root     7 Mar 16 16:11 /usr/bin/python -> python2
lrwxrwxrwx. 1 root root     9 Mar 16 16:11 /usr/bin/python2 -> python2.7
-rwxr-xr-x. 1 root root  7144 Nov 16 22:23 /usr/bin/python2.7
lrwxrwxrwx. 1 root root     9 Apr 12 03:30 /usr/bin/python3 -> python3.6
-rwxr-xr-x. 2 root root 11328 Nov 16 16:59 /usr/bin/python3.6
-rwxr-xr-x. 2 root root 11328 Nov 16 16:59 /usr/bin/python3.6m
lrwxrwxrwx. 1 root root    10 Apr 12 03:30 /usr/bin/pyvenv -> pyvenv-3.6
-rwxr-xr-x. 1 root root   435 Nov 16 16:57 /usr/bin/pyvenv-3.6
```

```shell-session
$ ls -l /usr/bin/pip*
-rwxr-xr-x. 1 root root 407 Oct 13 16:03 /usr/bin/pip3
lrwxrwxrwx. 1 root root   9 Apr 12 03:30 /usr/bin/pip-3 -> ./pip-3.6
lrwxrwxrwx. 1 root root   8 Apr 12 03:30 /usr/bin/pip-3.6 -> ./pip3.6
-rwxr-xr-x. 1 root root 407 Oct 13 16:03 /usr/bin/pip3.6
```

<font color="red">**注意**
ここで`/usr/bin/python`のリンク先を`python3`に変更してはいけない。なぜならばyumをはじめとする多くのコマンドがPython 2.xに依存しているからだ。シンボリックリンクを張り替えるとトラブルが発生するので注意が必要だ。</font>

7.`pip3 --version`を実行すると、ライブラリのインストール先がわかる。

```shell-session
$ pip3 --version
pip 9.0.3 from /usr/lib/python3.6/site-packages (python 3.6)
```

# 4. 安全なPython環境の切り替え

複数バージョンのPythonがあるとき、どのようにPythonのバージョンを切り替えるか。また、Pythonでは必須のライブラリをどのように管理するのか。

Pythonのバージョンを切り替えるだけならば、古典的なaliasを使う方法がある。

しかし、独断と偏見の推奨は**venv**による仮想環境を使用する方法である。この方法ならば、Pythonのライブラリも含めて完全に独立な環境を構築できるからだ。

```shell-session:ailiasを切る方法
alias python='/usr/bin/python3'
```

### 4-1. venvとは

Pythonには、1つのマシンで複数バージョンのPythonやPythonパッケージを管理する方法がたくさんある。これらの中で、もっとも一般的なのが**venv**だろう。**venv**は、従来の**virtualenv**がPython 3.3から標準機能として取り込まれたものだ。

### 4-2. venvの基本文法

venvの基本文法は以下のとおり。


```shell-session:仮想環境の作成（Python3）
python3 -m venv ＜環境パス名＞
```

```shell-session:仮想環境の作成（Python2）
python2 -m venv ＜環境パス名＞
```

```shell-session:仮想環境の有効化
source ＜環境パス名＞/bin/activate
```

```shell-session:仮想環境の無効化
deactivate
```

### 4-3. venvを使用する

1. 実際に試してみよう。はじめにmyenvという環境を作成する。

```shell-session
$ python3 -m venv myenv
```

3.指定した＜環境パス名＞のフォルダやファイルが作成されている。

```shell-session
$ ls -F
myenv/

$ ls -l myenv/
total 4
drwxrwxr-x. 2 foo foo 173 Apr 12 04:57 bin
drwxrwxr-x. 2 foo foo   6 Apr 12 04:57 include
drwxrwxr-x. 3 foo foo  23 Apr 12 04:57 lib
lrwxrwxrwx. 1 foo foo   3 Apr 12 04:57 lib64 -> lib
-rw-rw-r--. 1 foo foo  69 Apr 12 04:57 pyvenv.cfg
```

4.仮想環境を有効化する。仮想環境が有効になると、プロンプトの先頭に仮想環境名が表示される。＜環境パス名＞の部分は、カレントディレクトリからの相対パスである。

```shell-session
$ source myenv/bin/activate
(myenv) [foo@hostname ~]$
```

5.Pythonのバージョンを確認すると、どちらもバージョンは3.6.8になっている。

```shell-session
(myenv) [foo@hostname ~]$ python -V
Python 3.6.8

(myenv) [foo@hostname ~]$ python3 -V
Python 3.6.8
```

6.このようになる理由は、どちらも仮想環境配下のPythonを参照してるからだ（ともにシンボリックリンク）。

```shell-session
(myenv) [foo@hostname ~]$ which python
~/myenv/bin/python
(myenv) [foo@hostname ~]$ which python3
~/myenv/bin/python3

(myenv) [foo@hostname ~]$ ls -l ~/myenv/bin/python*
lrwxrwxrwx. 1 foo foo 7 Apr 14 07:00 /home/foo/myenv/bin/python -> python3
lrwxrwxrwx. 1 foo foo 16 Apr 14 07:00 /home/foo/myenv/bin/python3 -> /usr/bin/python3
```

7.インストールされているPythonパッケージを表示する。

```shell-session
(myenv) [foo@hostname ~]$ pip list --format=columns
Package    Version
---------- -------
pip        9.0.3
setuptools 39.2.0
```

8.datetimeライブラリをインストールする。このとき重要なのは、仮想環境「myenv」にだけdatetimeがインストールされることだ。

```shell-session
(myenv) [foo@hostname ~]$ pip install datetime
```

9.datetimeライブラリをインストールしたので、利用できるライブラリが増えている。

```shell-session
(myenv) [foo@hostname ~]$ pip list --format=columns
Package        Version
-------------- -------
DateTime       4.3
pip            9.0.3
pytz           2021.1
setuptools     39.2.0
zope.interface 5.3.0
```

9.仮想環境では、作成した仮想環境配下にライブラリがインストールされる。

```shell-session
$ pip --version
pip 9.0.3 from /home/foo/myenv/lib64/python3.6/site-packages (python 3.6)
```

10.`deactivate`で仮想環境を無効にすると、プロンプトが元に戻る。

```shell-session
(myenv) [foo@hostname ~]$ deactivate
[foo@hostname ~]$
```

11.再びライブラリを確認すると、仮想環境とは独立していることがわかる。

```shell-session
[foo@hostname ~]$ pip3 list --format=columns
Package    Version
---------- -------
pip        9.0.3
setuptools 39.2.0
```

# 5. Software CollectionsからPythonをインストールする

RHEL7やCentOS 7で、Python 3.6以外が必要なときはSoftware Collectionsを使用する。ここではSoftware Collectionsと、その使い方を説明する。

### 5.1. Software Collectionsとは

Software Collections（SCL）とは、標準リポジトリには含まれない、より新しいパッケージをベンダーが提供する仕組みである。RHEL系ディストリビューションでは、ベンダーサポートや互換性の観点から、同一メジャーバージョン内ではパッケージのバージョンをできるだけ固定化している。

しかし、実際の現場では、より新しいバージョンを使いたいことがある。EPELや本家サイトが提供するRPMパッケージを使用する方法もあるが、そのようなパッケージは無保証だ。

そのためベンダーサポートの範囲でパッケージを提供する仕組みがSoftware Collectionsである。おもに開発言語系のパッケージ提供されている。たとえばRHEL7ではPHP 5.4だが、Software CollectionsではPHP 7.3が提供されている。

当初RHELの仕組みとして提供されたものだが、CentOSやOracle Linuxでも提供されている。CentOSはノンサポートなので本来意図したサポートの有無は関係ないが、仕組みとして便利なので提供しているようだ。

### 5.2. Software Collectionsを有効にする

それでは実際にSoftware CollectionsのPython 3.8をインストールしてみよう。

1.Software Collectionsのリポジトリがあるか。あるときには、有効（enabled）になっているかを確認する。リポジトリ名はディストリビューションによって異なる。

| Linux Distribution | Repository Name |
|:--|:--|
| Red Hat Enterprise Linux 7  |  rhel-server-rhscl-7-rpms |
| CentOS 7  | centos-sclo-rh |
| Oracle Linux 7  | ol7_software_collections |

**全ディストリビューション共通**

```shell-session
$ yum repolist all | grep -e centos-sclo -e rhel-server-rhscl-7-rpms -e software
```

```shell-session:例：リポジトリ定義はあり、有効（enabled）になっている
centos-sclo-rh/x86_64               CentOS-7 - SCLo rh           enabled:  7,154
```

**RHELのとき**
RHELでは`yum repolist`が遅いので、コチラのコマンドが推奨。

```shell-session
# subscription-manager repos --list | grep -5 rhel-server-rhscl-7-rpms
リポジトリー ID:  rhel-7-server-satellite-tools-6.4-rpms
リポジトリー名:   Red Hat Satellite Tools 6.4 (for RHEL 7 Server) (RPMs)
リポジトリー URL: https://cdn.redhat.com/content/dist/rhel/server/7/7Server/$basearch/sat-tools/6.4/os
有効:             0
```

2.リポジトリの定義があり、無効（disable）のときは有効にする。

```shell-session:RHEL以外
# yum-config-manger --enable ＜リポジトリ名＞
```

```shell-session:RHEL
# subscription-manager repos --enable rhel-server-rhscl-7-rpms
```

3.CentOSやOracle Linuxでリポジトリの定義がないときはインストールする。

```shell-session:CentOS7のとき
# yum install centos-release-scl -y
```

```shell-session:OracleLinux7のとき
# yum oracle-softwarecollection-release-el7 -y
```

4.Python 3.8をインストールする。

```shell-session
# yum install rh-python38 -y
```

<font color="blue">**ヒント：**上記の例ではPython 3.8をインストールしているが、今後3.9以降のバージョンが追加される可能性もある。Software Collectionsで提供しているPythonのバージョンは`yum list rh-python*`で確認できる。</font>

5.Software Colletionsのパッケージは、インストールしただけでは有効にならない。そのため次のコマンドを実行する。bashを指定していることから推測できるように、`scl enable`で有効になるのは起動するシェル内だけだ。

```shell-session
$ scl enable rh-python38 bash

$ python -V
Python 3.8.6
```

6.`scl enable`を実行した環境では、Software CollectionsでインストールしたPythonが有効になっている。

```shell-session
$ which python
/opt/rh/rh-python38/root/usr/bin/python
```

7.シンボリックリンクが張られているため、`scl enable`実行後は`pytnon`、`python3`、`python3.8`いずれのコマンドでもPython 3.8が起動する。

```shell-session
$ ls -l /opt/rh/rh-python38/root/usr/bin/python*
lrwxrwxrwx. 1 root root     9 Apr 12 17:55 /opt/rh/rh-python38/root/usr/bin/python -> ./python3
lrwxrwxrwx. 1 root root     9 Apr 12 17:55 /opt/rh/rh-python38/root/usr/bin/python3 -> python3.8
-rwxr-xr-x. 1 root root 15280 Dec 24 01:29 /opt/rh/rh-python38/root/usr/bin/python3.8
```

8.環境変数もPython 3.8向けに設定されている。

```shell-session
$ env | grep python
MANPATH=/opt/rh/rh-python38/root/usr/share/man:
X_SCLS=rh-python38
LD_LIBRARY_PATH=/opt/rh/rh-python38/root/usr/lib64
PATH=/opt/rh/rh-python38/root/usr/local/bin:/opt/rh/rh-python38/root/usr/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/foo/.local/bin:/home/foo/bin
XDG_DATA_DIRS=/opt/rh/rh-python38/root/usr/share:/usr/local/share:/usr/share
PKG_CONFIG_PATH=/opt/rh/rh-python38/root/usr/lib64/pkgconfig
```

9.元に戻るには`exit`を実行する。これで終了だ。

```shell-session
$ exit
exit

$ python -V
Python 2.7.5
```

### 5.3. Software Collectionsまとめ

これまで見てきたように、Software Collectionsを使用するには、インストールに加えて、使用するたびに`scl enable`を実行する必要がある。

面倒と考えることもできるが、シェルセッション単位に有効化するので、独立性が高いとも言える。同時に複数ユーザーで使用するシステムでは混乱が少ないだろう。また`venv`を併用することも可能だ。

**Software Collectionsの利用手順**

* Software CollectionsのPythonをインストールする
* `scl enable`で使用するPythonを有効にする
* `exit`で、有効にしたSoftware Collectionsを無効にする

# 6. Amazon Linux 2のExtras libraryからPythonをインストールする

Amazon Linuxで、標準リポジトリに含まれていないパッケージを使用するときは、Extras libraryが推奨されている。CentOSのSoftware Collectionsも使用できるが、両方にあるならばExtras libraryを使用すべきだろう。

そこでExtras libraryのPython 3.8をインストールする方法を説明する。

1. Amazon Linux 2のデフォルトは2.7.18だ。

```shell-session
$ python -V
Python 2.7.18
```

2.Extras libraryにはpython3.8がある。

```shell-session
$ amazon-linux-extras | grep python
 44  python3.8                available    [ =stable ]
```

3.python3.8をインストールする。

```shell-session
$ sudo amazon-linux-extras install python3.8
```

4.バージョンを確認すると3.8.5がインストールされる。

```shell-session
$ python3.8 -V
Python 3.8.5
```

5.python3.8以外にも、pydoc3.8やpip3.8がインストールされている。

```shell-session
$ ls -l /usr/bin/py*3*
-rwxr-xr-x 1 root root   78 Feb 18 01:25 /usr/bin/pydoc3.8
-rwxr-xr-x 1 root root 7048 Feb 18 01:25 /usr/bin/python3.8

$ ls -l /usr/bin/pip*
lrwxrwxrwx 1 root root   8 Apr 12 07:36 /usr/bin/pip-3.8 -> ./pip3.8
-rwxr-xr-x 1 root root 208 May 19  2020 /usr/bin/pip3.8
```

6.インストールしたRPMパッケージを降順（新しい順）に表示すると、python38で始まるパッケージがインストールされている。

```shell-session
$ rpm -qa --last |head
python38-libs-3.8.5-1.amzn2.0.2.x86_64        Mon 12 Apr 2021 07:36:11 AM UTC
python38-setuptools-38.4.0-4.amzn2.0.1.noarch Mon 12 Apr 2021 07:36:09 AM UTC
python38-pip-9.0.3-2.amzn2.0.1.noarch         Mon 12 Apr 2021 07:36:09 AM UTC
python38-3.8.5-1.amzn2.0.2.x86_64             Mon 12 Apr 2021 07:36:09 AM UTC
rootfiles-8.1-11.amzn2.noarch                 Fri 26 Mar 2021 05:36:26 PM UTCq
```

7.あとの使い方は標準リポジトリのpython3と同じだ。`python3.8`コマンドで起動してもいいし、次のように`venv`を使ってもいい。

```shell-session
python3.8 -m venv ＜環境パス名＞
```

# 7. ライブラリ（パッケージ）の管理の注意点

venvを使用しているときには関係ないが、rootでパッケージをインストールしている記事を見かける。推奨されない方法なので注意してほしい。

```shell-session:どちらも同じ意味
$ sudo pip3 install ＜パッケージ名＞
$ sudo python3 -m pip install  ＜パッケージ名＞
```

rootで実行する理由は、インストール先ディレクトリが`/usr/local/lib/python3.6/site-packages/`や`/usr/local/lib64/python3.6/site-packages/`であるために「Permission denied」で失敗するからだ。

実際にコマンドを実行したときのメッセージでは、次のように`--user`オプションを使うことを推奨される。このオプションを指定するとOSユーザーの`~/.local`配下にインストールされるためroot権限は必要ない。

```shell-session
WARNING: Running pip install with root privileges is generally not a good idea.
Try pip3 install --user instead.
```

rootで実行することの副作用や悪影響を十分理解したうえで使うことは否定しないが、`--user`でも考慮事項はあるので、venvなどの仮想環境が好ましいと言える。

# 8. まとめ

* **RHEL7系でPython 3.6を使用するにはpython3をインストールする**
  * pythonコマンドでは2.7が起動され、python3コマンドでは3.6が起動される
  * ただしAmazon Linux 2のpython3は3.7
  * pythonコマンドで3.xを起動する代表的な方法には、aliasを使用する方法と、venvを使用する方法がある
* **venvを使用すると、独立したPython仮想環境を構築できる**
* **Python 3.8を使用するには、Software Collectionsをインストールする**
  * これらの環境でもvenvを使用できる
  * Software CollectionsでインストールしたPythonを使用するには、`scl enable`コマンドでシェルセッション単位に有効化する
  * 利用者ごとに有効化するので独立性が高い
* **Amazon Linux 2でPython 3.8を使用するにはExtras libraryをインストールする**
* **Pythonライブラリをpipでインストールするときはvenvを使用する**