pyROOT を anaconda で install した python から  import して PyThreadState_Get: no current thread のエラーが出た時の対処法

# 前提条件 

anaconda で python を install して、

```python
import ROOT
```
で pyROOT を起動した時に、

```sh: 
Fatal Python error: PyThreadState_Get: no current thread
```
が出た場合の対処方法を記述する。

# 対処方法

## otool でライブラリの確認

otool -L で libPyROOT.so のライブラリを確認する。

```sh: 
> otool -L /Users/syamada/work/software/root/root-6.06.04-compiled/lib/root/libPyROOT.so
                                 
/Users/syamada/work/software/root/root-6.06.04-compiled/lib/root/libPyROOT.so:
/Users/syamada/work/software/root/root-6.06.04-compiled/lib/root/libPyROOT.so (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
/Users/syamada/work/software/root/root-6.06.04-compiled/lib/root/libCore.so (compatibility version 0.0.0, current version 0.0.0)
/Users/syamada/work/software/root/root-6.06.04-compiled/lib/root/libRIO.so (compatibility version 0.0.0, current version 0.0.0)
/Users/syamada/work/software/root/root-6.06.04-compiled/lib/root/libTree.so (compatibility version 0.0.0, current version 0.0.0)
libpython2.7.dylib (compatibility version 2.7.0, current version 2.7.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.1.0)
```

一見よさそうに見えてしまうが、libpython2.7.dylib に問題がある。このように表示された場合は、mac 純正の python の libpython2.7.dylib を指している。

## install_name_tool でライブラリの変更

上記の libpython が anaconda の python を示すように変更する。

変更するには install_name_tool を使う。使い方は、

```sh:
install_name_tool -change 変更したいライブラリ 更新したいライブラリ オブジェクトファイルの名前 
```
である。

私の環境では下記になる。

```sh:
sudo install_name_tool -change libpython2.7.dylib /Users/syamada/anaconda/lib/libpython2.7.dylib /Users/syamada/work/software/root/root-6.06.04-compiled/lib/root/libPyROOT.so
```

これでもう一度 otool を実行すると、

```sh:
> otool -L /Users/syamada/work/software/root/root-6.06.04-compiled/lib/root/libPyROOT.so
...
/Users/syamada/anaconda/lib/libpython2.7.dylib (compatibility version 2.7.0, current version 2.7.0)
```
となり、anaconda の libpython を指すように変更されている。
これで import ROOT してもエラーはでなくなる。

## pyenv ユーザ向け
pyenv などによって複数のpython 環境を共存させていると、同様の問題に直面する。このとき、上記の方法をしても、現象が改善しないことがある。

``` sh:
> otool -L /Users/hoge/software/root/lib/libPyROOT.so
```
としてみると、

``` sh:
/Users/hoge/software/root/lib/libPyROOT.so:
	@rpath/libPyROOT.6.16.so (compatibility version 6.16.0, current version 6.16.0)
	@rpath/libTree.6.16.so (compatibility version 6.16.0, current version 6.16.0)
	/System/Library/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.10)
	@rpath/libtbb.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libRIO.6.16.so (compatibility version 6.16.0, current version 6.16.0)
	@rpath/libCore.6.16.so (compatibility version 6.16.0, current version 6.16.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
```
このとき、/System/Library/Frameworks/Python.framework/Versions/2.7/Python が、pyenv などで入れたanaconda の場合install_name_tool をしてもなぜか変わらない。しかし、

```sh:
sudo install_name_tool -change /System/Library/Frameworks/Python.framework/Versions/2.7/Python /Users/hoge/.pyenv/versions/anaconda2-5.3.1/lib/libpython2.7.dylib /Users/hoge/software/root/lib/libPyROOT.so
```
とすると、

```sh:
$ otool -L /Users/hoge/software/root/lib/libPyROOT.so
/Users/hoge/software/root/lib/libPyROOT.so:
	@rpath/libPyROOT.6.16.so (compatibility version 6.16.0, current version 6.16.0)
	@rpath/libTree.6.16.so (compatibility version 6.16.0, current version 6.16.0)
	/Users/hoge/.pyenv/versions/anaconda2-5.3.1/lib/libpython2.7.dylib (compatibility version 2.7.0, current version 2.7.10)
	@rpath/libtbb.dylib (compatibility version 0.0.0, current version 0.0.0)
	@rpath/libRIO.6.16.so (compatibility version 6.16.0, current version 6.16.0)
	@rpath/libCore.6.16.so (compatibility version 6.16.0, current version 6.16.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
```
のように、pyenv 共存させているanaconda python を参照でき、pyROOT を使用できる。

- StackOverflow: https://stackoverflow.com/questions/15678153/homebrew-python-on-mac-os-x-10-8-fatal-python-error-pythreadstate-get-no-cu

[追記] 2019.1.5 : Mac OS 10.14.6, rootのバージョン v6-18-04@v6-18-04 のバイナリをダウンロードし、パスを通した。

``` bash:
sudo install_name_tool -change /System/Library/Frameworks/Python.framework/Versions/2.7/Python /Users/syamada/.pyenv/versions/anaconda2-2019.07/lib/libpython2.7.dylib /Users/syamada/work/software/root/root_v6.18.04_binaries/lib/libPyROOT.so
```

デフォルトでmac純正のPythonを見ているため、.pyenvの下のanacondaのpythonのlibpython2.7.dylib をみるように変更したら動いた。(ソースコードでcmakeの設定を正しくpyenvのanaconda python 2系をみるように設定しても、configureでコケてしまい、理由は分からず。)

## 未解決現象

基本的に、エラーにであったら上記対応をすればOKである。理解できてない状況として、上記の不整合があったとしても動く場合がある。私の環境では、ターミナル上で > python pythonスクリプト(import ROOTを含む) を直打した場合はなぜか動く。一方、実行ファイルにしたり、sh スクリプトから動かすとダメである。

# 参考文献

- otool の使い方 : http://mactkg.hateblo.jp/entry/2012/05/03/202549