【Python2to3アップデート方法】Python3系のインストール

## 目次
- [【Python2to3アップデート方法】目次](https://qiita.com/Esfahan/items/067484ee0cb3dd374992)

## 概要
Python2系を3系にアップデートする手順や、バージョンについて説明する。

## インストール方法
ここでは、以下の3つのインストール方法を紹介する。

| 方法 | version | 備考 |
| --- | --: | --- |
| [CentOS:7.5にyumでインストール](#centos7にyumで36をインストール) | 3.6 | yumでは3.6までしかインストールできない |
| [ubuntu:18.04にapt-getでインストール](#ubuntuのapt-getで37をインストール) | 3.7 | apt-get-で3.7をインストール可能 |
| [ソースファイルをコンパイルしてインストール](#ソールファイルをコンパイルして37インストール) | 3.7 | - |


## CentOS7にyumで3.6をインストール
CentOS7のyumでは、Python3.6が最新なので3.6をインストールする。

#### レポジトリを追加
iusから取得する場合(3.6.7がインストールされる)

```shell-session
$ sudo yum install -y https://centos7.iuscommunity.org/ius-release.rpm
```

epelから取得する場合(3.6.6がインストールされる)

```shell-session
$ sudo yum install -y epel-release
```

#### インストール
iusから取得する場合

```shell-session
$ sudo yum install -y python36u python36u-libs python36u-devel python36u-pip
============================================================================================================================================================================================================
 Package                                                  Arch                                       Version                                                  Repository                               Size
============================================================================================================================================================================================================
Installing:
 python36u                                                x86_64                                     3.6.7-1.ius.centos7                                      ius                                      57 k
 python36u-devel                                          x86_64                                     3.6.7-1.ius.centos7                                      ius                                     839 k
 python36u-libs                                           x86_64                                     3.6.7-1.ius.centos7                                      ius                                     8.9 M
 python36u-pip                                            noarch                                     9.0.1-1.ius.centos7                                      ius                                     1.8 M
Installing for dependencies:
 python36u-setuptools                                     noarch                                     39.0.1-1.ius.centos7                                     ius                                     642 k

Transaction Summary
============================================================================================================================================================================================================
Install  4 Packages (+1 Dependent package)
```

epelから取得する場合

```shell-session
$ sudo yum install -y --enablerepo=epel python36 python36-libs python36-devel python36-pip
============================================================================================================================================================================================================
 Package                                               Arch                                     Version                                                 Repository                                     Size
============================================================================================================================================================================================================
Installing:
 python36                                              x86_64                                   3.6.6-5.el7                                             epel                                           66 k
 python36-devel                                        x86_64                                   3.6.6-5.el7                                             epel                                          850 k
 python36-libs                                         x86_64                                   3.6.6-5.el7                                             epel                                          8.5 M
 python36-pip                                          noarch                                   8.1.2-8.el7                                             epel                                          1.6 M
Installing for dependencies:
 dwz                                                   x86_64                                   0.11-3.el7                                              centos-base                                    99 k
 perl-srpm-macros                                      noarch                                   1-8.el7                                                 centos-base                                   4.6 k
 python-rpm-macros                                     noarch                                   3-23.el7                                                epel                                          7.7 k
 python-srpm-macros                                    noarch                                   3-23.el7                                                epel                                          7.2 k
 python3-rpm-macros                                    noarch                                   3-23.el7                                                epel                                          6.8 k
 python36-setuptools                                   noarch                                   39.2.0-3.el7                                            epel                                          631 k
 redhat-rpm-config                                     noarch                                   9.1.0-87.el7.centos                                     centos-base                                    81 k

Transaction Summary
============================================================================================================================================================================================================
Install  4 Packages (+7 Dependent packages)
```

**以降、iusからダウンロードした場合の例です。epelもだいたい同じですが、多少インストールされるものに違いがあります。**


インストールすると、python関連のコマンドが以下のように増える。
python3.6mとは、--with-pymallocオプションが設定されたもの。
pymallocについては、[こちら](https://docs.python.org/ja/3/c-api/memory.html#the-pymalloc-allocator)を参照。

```shell-session
$ ls -1 /usr/bin/* | grep python
/usr/bin/python
/usr/bin/python2
/usr/bin/python2.7
/usr/bin/python3
/usr/bin/python36
/usr/bin/python3.6
/usr/bin/python3.6-config
/usr/bin/python3.6m
/usr/bin/python3.6m-config
/usr/bin/python3.6m-x86_64-config
/usr/bin/python3-config
```

#### シンボリックリンクを貼る
pythonコマンドでpython3.6を実行できるようにする。

```shell-session
$ sudo ln -s /usr/bin/python3.6 /usr/local/bin/python
$ python --version
Python 3.6.7
```

#### pipについて
python36u-pipをインストールした直後では、pipコマンドは`pip3.6`のみが存在している。

iusの場合

```shell-session
$ which pip3.6
/usr/bin/pip3.6
```

epelの場合

```shell-session
$ which pip3.6
/usr/local/bin/pip3.6
```

pip3.6コマンドを実行すると、pipをupgradeしろと出るのでupgradeする。

```
You are using pip version 9.0.1, however version 19.0.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
```

```
$ sudo pip3.6 install --upgrade pip
```

そうすると、pipコマンドが以下の3つに増える。

```shell-session
-rwxr-xr-x 1 root root 218 Apr 18 01:54 /usr/bin/pip
-rwxr-xr-x 1 root root 218 Apr 18 01:54 /usr/bin/pip3
-rwxr-xr-x 1 root root 218 Apr 18 01:54 /usr/bin/pip3.6
```

ただし、全て同じ場所を参照しているようなので、全て同じだと思われる。

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

### python36とpython36uの違い
ちなみに、yum searchをすると分かるが、`python36`と`python36u`の2つのパッケージが用意されている。この2つの違いについて調べてみた。

```shell-session
$ sudo yum search yum search python36
python36.x86_64 : Interpreter of the Python programming language
python36u.x86_64 : Interpreter of the Python programming language
```

[python36uとは一体なんなのか調べてみた。](https://qiita.com/yoshiken/items/49bad2a1306073052bcd)

> EPELの後発であるIUSが独自の基準で選んだpythonのリビジョンやらがEPELと違うので同じpackage nameだと不都合だからuをつけたんだろう

[CentOS python3 package difference between python36 and python36u](https://unix.stackexchange.com/questions/466525/centos-python3-package-difference-between-python36-and-python36u)
> python36u is an alternative build provided by IUS; python36 is an EPEL package.
> yum info python36 python36u will show you different repos for the two, and it's likely that the IUS one has a slightly higher minor version number than the EPEL package.

結論としては、提供元が違うだけで、大きな差はなさそう。

## Ubuntuのapt-getで3.7をインストール
ちなみに、Ubuntuではあまり動作確認していません。

### Python3.7のインストール

```shell-session
$ sudo apt-get install python3.7
```

### pip3のインストール

```shell-session
$ sudo apt-get install python3-pip
```


## ソールファイルをコンパイルして3.7インストール
CentOS7.5でPython3.7をインストールするには、OpenSSL1.02以上が必要となる。
(Python3.6をインストールする場合は現行のversionでOK)

現行もversionでPythonのインストールを続けると、コンパイル時に以下のように、ssl moduleをbuildできないというログが出力される。

```
Could not build the ssl module!
Python requires an OpenSSL 1.0.2 or 1.1 compatible libssl with X509_VERIFY_PARAM_set1_host().
LibreSSL 2.6.4 and earlier do not provide the necessary APIs, https://github.com/libressl-portable/portable/issues/381
```

現行のopensslのversionを調べてみると、1.0.2が入っているように見えるが、これでは駄目なようだ。
`yum install -y openssl-devel`をしても結果は変わらなかった。

```shell-session
$ rpm -qa | grep openssl
openssl-libs-1.0.2k-8.el7.x86_64
```

そのため、OpenSSL1.1.1をインストールすることにする。

### OpenSSL-1.0.2は2019-12-31にEOL
また、1.0.2は2019-12-31にEOLなようなので、1.1.1を入れることにする。
https://www.openssl.org/policies/releasestrat.html

> The next version of OpenSSL will be 3.0.0.
Version 1.1.1 will be supported until 2023-09-11 (LTS).
Version 1.1.0 will be supported until 2019-09-11.
Version 1.0.2 will be supported until 2019-12-31 (LTS).
Version 1.0.1 is no longer supported.
Version 1.0.0 is no longer supported.
Version 0.9.8 is no longer supported.

### OpenSSLのインストール
OpenSSL1.1.1を入れます。以下を参考にしてインストールしてください。
「OpenSSLを共有ライブラリに追加する」も実施してください。（実施しないとpipが使えません。）

参考：[CentOS7にOpenSSL1.1.1をインストール](https://qiita.com/Esfahan/items/4e2002f4a24589b2d0bf)

ちなみに、既存のOpenSSLは残したまま、別途1.1.1をインストールするし、Pythonの./configureオプションで1.1.1のライブラリパスを指定するインストール方法を実施する。

### 依存関係のインストール
以下をインストールする。

```shell-session
$ sudo yum -y install zlib \
                      tk-devel \
                      tcl-devel \
                      ncurses-devel \
                      gdbm-devel \
                      readline-devel \
                      zlib-devel \
                      bzip2-devel \
                      sqlite-devel \
                      openssl-devel \
                      libXext.x86_64 \
                      libSM.x86_64 \
                      libXrender.x86_64 \
                      gcc \
                      gcc-c++ \
                      libffi-devel \
                      python-devel \
                      patch \
                      bzip2 \
                      make
```

matplotlib使うなら下記もインストールする。
後から追加した場合、Pythonのリビルドが必要となる。

```shell-session
$ sudo yum install -y tk.x86_64 tk-devel.x86_64 tkinter.x86_64
```

### Pythonのダウンロード
以下からインストールするversionを選ぶ。
https://www.python.org/

ここでは3.7をインストールする。

```shell-session
$ sudo curl https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz -o /usr/local/src/Python-3.7.3.tgz
```

### Pythonのインストール
`--with-openssl=/usr/local/openssl-1.1.1`で先程インストールしたOpenSSLのパスを指定する。
`--with-ensurepip`を付けることでpip3もインストールする。
`--enable-optimizations`を付けると、[11%ほどパフォーマンスが上がるらしい](https://qiita.com/ichylinux/items/cdd205dc3ef6bdd86b4a)。ただし、makeにすごく時間がかかる。

```shell-session
$ cd /usr/local/src
$ sudo tar xvfz Python-3.7.3.tgz
$ cd Python-3.7.3
$ sudo ./configure --enable-unicode=ucs4 \
                   --prefix=/usr/local \
                   --with-openssl=/usr/local/openssl-1.1.1 \
                   --with-ensurepip \
                   --enable-optimizations
$ sudo make
$ sudo make altinstall
```

#### make altinstallについて
https://docs.python.org/ja/3/using/unix.html#building-python


> 警告 make install は python3 バイナリを上書きまたはリンクを破壊してしまうかもしれません。そのため、make install の代わりに exec_prefix/bin/pythonversion のみインストールする make altinstall が推奨されています。

### インストールされたことを確認
以下にインストールされる。

```shell-session
$ sudo ls -l /usr/local/bin/
total 24644
-rwxr-xr-x 1 root root      101 Apr 17 11:22 2to3-3.7
-rwxr-xr-x 1 root root      241 Apr 17 11:22 easy_install-3.7
-rwxr-xr-x 1 root root       99 Apr 17 11:22 idle3.7
-rwxr-xr-x 1 root root      223 Apr 17 11:22 pip3.7
-rwxr-xr-x 1 root root       84 Apr 17 11:22 pydoc3.7
-rwxr-xr-x 2 root root 12603000 Apr 17 11:22 python3.7
-rwxr-xr-x 2 root root 12603000 Apr 17 11:22 python3.7m
-rwxr-xr-x 1 root root     3105 Apr 17 11:22 python3.7m-config
-rwxr-xr-x 1 root root      441 Apr 17 11:22 pyvenv-3.7
```

## shebangについて
shebangの書き方だが、大きく分けて以下の2つがある。

### `#!/usr/bin/python`
こちらは、/usr/bin/pythonをインタプリタとして定義している。逆に言うと、/usr/bin/pythonが存在していない場合はエラーとなる。

### `#!/usr/bin/env python`
こちらは、PATHので定義されているディレクトリのどこかにpythonが存在していれば、それを採用する。複数pythonが存在している場合は、PATHで定義されている順番に依存する。PATHの内容は以下で確認。

```shell-session
$ echo $PATH
```

参考： [「#!/usr/bin/python」と「#!/usr/bin/env python」の違い](http://zashikiro.hateblo.jp/entry/2012/09/22/125953)

## 参考
- [Python 3 を CentOS 7 に yum でインストールする手順](https://weblabo.oscasierra.net/python3-centos7-yum-install/)
- [CentOS7にPython3とpipをインストールする](http://python.zombie-hunting-club.com/entry/2017/11/03/223832)