M1MacのRosettaとARM環境にpyenv + pipenvの環境構築を行う

## はじめに
M1macパソコンが出始めて1年とちょっと？くらい経ちまして、待望の14inchと8GB以上のメモリが付けられる新型macbookproが発売されました。僕は今までintel製のmacbookを持っていたのですが、電池消費量や性能などの観点から買い替えを決意。一ヶ月経ってパソコンが届いたのですが、待っていたのは周りの人たちがたちが苦しんでいたM1macのpython環境構築でした。

さて、このM1macパソコン。pyenvが対応していなかったことからcondaを選択する人も多かったとお思います。しかし、調べてみるとpyenvって3.9系以上は対応しているのですね。でも3.9系ではなくそれより前のバージョンを使用したい人も多いはずです。機械学習を目的としてる人は特に。
この記事はたくさんあるサイトを確認して、それをまとめたものになります。

## 注意
ARM環境ではPythonは **3.9系以上** を入れることができます。
Rosetta環境では**3.9系未満**も入れることができます。
ARM環境で3.9系未満を入れる記事ではありません。ご了承ください

この記事は
**Rosetta環境では3.9系やそれ未満をを、ARM系では3.9系を入れる記事です。**
![無題のプレゼンテーション (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1955797/6eb40abb-84a5-03bb-ae70-5e12184b7efb.png)



## 動作環境 & 使用するシステム
チップ：M1 Pro
メモリ：16GB
バージョン：macOS Monterey 12.0.1

**使用するシステム**
パッケージ管理：Homebrew
pythonバージョン管理：pyenv
ライブラリ管理：pipenv
テキストエディタ：好きなものをお使いください。



## Homebrewのインストール
まずはHomebrewをインストールします。
Homebrewとは、パッケージ管理システムです。インストールからアンインストール・バージョンアップやバージョンダウンまで一元管理してくれるシステムです。
また、RosettaとARMでインストールするとき保存場所が違うのでARM版とRosetta版で二つインストールしてください。
インストールするときは下のコードをコピペしてください。
**ARM64(Rosettaを使用していない)にインストール**

```
$ uname -m
arm64

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
----

$ which brew
opt/homebrew/bin/brew
```

**Rosettaにインストール**
1. ターミナルを右クリック→
1. ロゼッタを使用して開くのチェックボックスにチェックを入れる。（初めての時はインストールが始まる）→
1. ターミナルを開く。　

```
$ uname -m
x86_64

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
----

$ which brew
/usr/local/bin/brew
```

## PATHを通すため、.zshrcを編集
この時点で、このパソコンにはHomebrewが二つ存在している状態です。
この状態では、PATHが混乱して、ARMなのにRosetta版のHomebrewを用いたり逆が行われたりする可能性があるので
しっかりと対策をしていかないといけません。そのために.zshrcを編集します。

以下を張り付けてください

```
if [ "$(uname -m)" = "arm64" ]; then
  eval "$(/opt/homebrew/bin/brew shellenv)"
  export PATH="/opt/homebrew/bin:$PATH"
else
  eval "$(/usr/local/bin/brew shellenv)"
fi
```


## pyenvをインストール
続いてpyenvをインストールします。

```
$ brew install pyenv
```
こちらもARMとRosetta両方インストールしてください。

## PATHを通すため、.zshrcを編集
通常PyenvでPATHを通すときは3行くらい書けば問題ないのですが、Homebrewと同様ARMとRosettaでは保存場所が違うので、条件式を用いてインタラクティブに変更する必要があります。
以下を.zshrcに張り付けてください。

```
if [ "$(uname -m)" = "arm64" ]; then
  # arm64
  export PYENV_ROOT="$HOME/.pyenv_arm64"
  export PATH="$HOME/.pyenv_arm64/bin:$PATH"
  eval "$(pyenv init -)"
else
  # x86_64
  export PYENV_ROOT="$HOME/.pyenv_x64"
  export PATH="$HOME/.pyenv_x64/bin:$PATH"
  eval "$(pyenv init -)"
fi
```

## Pythonをインストールする
ここまでくればあと少しです。
RosettaもARMも3.9系以上を入れる場合は、

```
$ pyenv install 3.9.1
```

:::note info
追記：2022/09/20
現在、3.8系は上記方法でRosettaでもpythonをインストールすることが可能となっています。
(Python3.8.6で検証)
:::

この一行で済んでしまいます。(3.9.1の部分を変えればそのバージョンをインストールできます。)
しかし、Rosettaで3.8系などをインストールするとき、先ほどのコードを入れると、

```
BUILD FAILED (OS X 12.0.1 using python-build 20180424)

Inspect or clean up the working tree at /var/folders/63/b9w9wr5d1j1_00j80p_047jc0000gn/T/python-build.20211123225241.27371
Results logged to /var/folders/63/b9w9wr5d1j1_00j80p_047jc0000gn/T/python-build.20211123225241.27371.log

Last 10 log lines:
        ret = sendfile(in, out, offset, &sbytes, &sf, flags);
              ^
./Modules/posixmodule.c:10432:5: warning: code will never be executed [-Wunreachable-code]
    Py_FatalError("abort() called from Python code didn't abort!");
```

このようになってしまいます。そこで色々調べてみると、下のコマンドを発見しました。このコードでインストールすることができました。
**3.8.2をインストール**

```
$ CFLAGS="-I$(brew --prefix openssl)/include -I$(brew --prefix bzip2)/include -I$(brew --prefix readline)/include -I$(xcrun --show-sdk-path)/usr/include" LDFLAGS="-L$(brew --prefix openssl)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix bzip2)/lib" pyenv install --patch 3.8.2 < <(curl -sSL https://github.com/python/cpython/commit/8ea6353.patch\?full_index\=1)
```
上記コードに
` pyenv install --patch 3.8.2 ` があるのですが、ここの3.8.2を入れたいバージョンに変えてください。
これで

```
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Downloading Python-3.8.2.tar.xz...
-> https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz
Installing Python-3.8.2...
patching file Misc/NEWS.d/next/macOS/2020-06-24-13-51-57.bpo-41100.mcHdc5.rst
patching file configure
Hunk #1 succeeded at 3382 (offset -44 lines).
patching file configure.ac
Hunk #1 succeeded at 498 (offset -12 lines).
python-build: use readline from homebrew
python-build: use zlib from xcode sdk
Installed Python-3.8.2 to /Users/username/.pyenv_x64/versions/3.8.2
```
と出ていれば成功です！

## pipenvでディレクトリごとに環境を作成
**ここからはarm環境でもRosetta環境でも好きな方をお使いください**
pipenvを使ってディレクトリごとに環境を作っていきます。これを行うことによって、Pythonのバージョンに合わせたライブラリを入れることができます。
**3.8.2用の環境を作成**

```
#Rosettaで開き、環境構築(ARMでもpipenvはinstallしてください)
$ uname -m
x86_64
$ brew install pipenv

#新しくディレクトリを作成し、その中に環境を作成
$ mkdir test
$ cd test
$ pipenv --python 3.8.2
---

#仮想環境に入る
$ pipenv shell
---

# ライブラリをインストール
$ pipenv install numpy pandas matplotlib
---
```
これで仮想環境作成完了です。あとはvsCodeを使うなり、jupyterを使うなり好きなようにPythonを楽しんでください！
## RosettaとARMをコマンドで変更する。

毎度毎度閉じて`ロゼッタを使用して開く`のチェックボックスを付けて起動したり、外して起動したり・・・面倒じゃないですか？
これをコマンドで解決してしまいましょう。
.zshrcを編集します。
下のコードを書いてください。

```
alias x86='arch -x86_64 zsh'
alias arm='arch -arm64e zsh'
```
これで終了です。

```
$ x86

$ uname -m
x86_64
$ pyenv versions
*system
3.9.1

$ arm

$ uname -m
arm
$ pyenv versions
system
3.9.1
3.8.2
・・・
```
このように`arm`や`x86`と打つだけでシステムを切り替えることができます。


## まとめ
この記事では、RosettaとARM環境の両方にpythonを使えるように環境構築を施しました。
少々面倒な場所も多かったと思いますが、次開くときはとても楽にpythonを楽しめると思います。
良きPythonライフを～ﾉｼ

## 参考にさせていただいたサイト
https://qiita.com/funatsufumiya/items/cec08f1ba3387edc2eed

https://qiita.com/tomtsutom0122/items/52487730001247fdc2c5

https://qiita.com/Butterthon/items/e7d1f379c828b41f3e19