macOSをアップグレードして、pythonもupgradeしたら(何きっかけか不明なんですが)今まで動いていたpythonのDb2ライブラリibm_dbがimportでエラーになるようになってしまいました。
メモとして、ここに解決策を書いておきます。
以下のversionでの動作です
- macOS: Ventura 13.2.1
- python: Python 3.11.2
- VS Code: 1.76.2 (Universal)
- gcc 8 (解決策として導入)
問題 import ibm_dbでエラー
エラーは具体的には以下のような感じです:
>>> import ibm_db
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: dlopen(/Users/xxxx/python_venv/db2/.db2_venv/lib/python3.11/site-packages/ibm_db.cpython-311-darwin.so, 0x0002): Symbol not found: ___cxa_throw_bad_array_new_length
Referenced from: <855AE640-1BCF-3A61-A65E-58F5490BFF43> /Users/xxxx/python_venv/db2/.db2_venv/lib/python3.11/site-packages/clidriver/lib/libdb2.dylib
Expected in: <31679759-38DC-357A-95C2-542EA70F295F> /usr/lib/libstdc++.6.dylib
Symbol not found: ___cxa_throw_bad_array_new_length
というエラーが出てます。
解決策
調べたところlibstdc++.6.dylib
とlibgcc_s.1.1.dylib
がどこかの(!)Mac OSのバージョンのからなくなったそうで、gcc version 8以降を導入して入手しておかなくてはならないそうです。
このあたりに書いてありました: https://github.com/ibmdb/python-ibmdb/issues/540
ということでgccを導入。brewで導入しました。その時デフォで入るversion12.2でやってみたところ、ところどころうまく動きませんでしたので、v8を入れておくのが無難です。
コマンドは以下:
brew install gcc@8
で、この導入したgccのライブラリーのパスをDYLD_LIBRARY_PATHに設定後、pythonを実行する必要があります。
export DYLD_LIBRARY_PATH=/usr/local/lib/gcc/8:$DYLD_LIBRARY_PATH
毎回コマンドを打つのもの面倒なので、~/.zshrc
に上記の一行入れてしまえば、次回からターミナルを開けば設定済みになります。
追加解決策 VSCodeのJupyter Notebookの場合
実際のところVSCodeのJupyter Notebookで使いたかったのですが、上記の設定をしたターミナルから直でcode .
で 立ち上げても、DYLD_LIBRARY_PATHがセットされてないという問題がありました。 ibm_dbをimportはできるのですが、DYLD_LIBRARY_PATHがセットされてないとDb接続時にカーネルがクラッシュします。
参考:
- https://github.com/microsoft/vscode-jupyter/wiki/Kernel-crashes
- https://github.com/microsoft/vscode-jupyter/wiki/Kernel-crashes-when-using-ibm-db
どうやらターミナルで設定された環境変数はVSCode上のJupyter Notebookで引き継がないそうで(なんで??)。
ワークスペースのフォルダー内に.env
ファイルを作成してそこに設定すればよいとのことで、そのようにしたのですが、他の環境変数は反映されるのになぜかDYLD_LIBRARY_PATH
という環境変数だけ反映されず。。。。
このあたりにいろいろ書いてありました: https://github.com/golang/vscode-go/issues/468#issue-672591555
この結論が代わりにLD_LIBRARY_PATH
を使えになってますが、この環境変数では動きませんでした。
いろいろやりましたが、どうしてもDYLD_LIBRARY_PATH
の設定ができず、結局VSCode上でJupyter Notebookを使いibm_dbを使いたい場合は、
Jupyter Notebookを解決策の環境で起動させ、そこにVSCodeから接続する、
とういう方法になると思います。
簡単にその方法です。
1. 解決策の環境のターミナルからJupyter Notebookの起動
VSCodeから繋ぐので、ちょっとしたオプションを入れます。
オプションipの値は、*
だと全てから接続を許可してしまうので、制限したい場合は接続元のipアドレスを入れてください。
jupyter notebook --ip='*' --no-browser
起動させると以下のようなメッセージが表示されます
[I 12:44:43.822 NotebookApp] ローカルディレクトリからノートブックをサーブ: /Users/nishito/python_venv/db2
[I 12:44:43.822 NotebookApp] Jupyter Notebook 6.5.3 is running at:
[I 12:44:43.822 NotebookApp] http://xxxxxxxxxxxxxxxxxxxx.local:8888/?token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[I 12:44:43.822 NotebookApp] or http://127.0.0.1:8888/?token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[I 12:44:43.822 NotebookApp] サーバを停止し全てのカーネルをシャットダウンするには Control-C を使って下さい(確認をスキップするには2回)。
表示された
http://xxxxxxxxxxxxxxxxxxxx.local:8888/?token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
をどこかにコピーしておきます(xxxxxの部分は環境で異なります)
2. VSCodeでカーネルを起動した Jupyter Notebookを設定
⌃⌥⌘N
で「新しいファイル」から「Jupyter Notebook」を選びます。または既存Jupyter Notebookのファイル(*.ipynb)を開きます。
1でコピーした実行中のJupyterサーバーのURLを入力し、Enterを押下します。
これでibm_dbがVSCodeのJupyter Notebookで無事importできるようになりました!
(ちょっと面倒)
3. Tips
Jupyter Notebookを停止したい時は、動作しているターミナルで Control-C 入力します(確認をスキップするには2回入力)。
尚、再度新規にJupyter Notebookを起動させた場合、tokenが変わりますので、再度カーネルの選択でJupyterサーバーのURLを入力し設定する必要があります。その際以前使用していたものは、ゴミ箱アイコンを使用して削除するようにしてください。
以上です。