minminの備忘録

フルスタックになりたいエンジニアの備忘録 → https://zuminblog.com/ へ引越し中

jupyter notebookで上位階層のモジュールをimportする

jupyter notebookから上位階層にあるモジュールをimportするときに、通常のpythonファイルのようにはいかなかったので、その解決方法を紹介したいと思います。
解決方法としては、以下のコマンドをimportの前に追加してあげれば良いだけです。

import sys
sys.path.append('..') #('')の中に探索元のpathを書く

以下、前提やら簡単な説明やらを書いていきます。

前提

以下のような階層を想定して、sample.py, sample.ipynbからhoge.py内のprint_fugaをimportしたいと思います。

|-- utils/
      |-- hoge.py
|-- examples/
      |-- sample.py
      |-- sample.ipynb

通常のpythonファイルでは

以下のように、sys.pathに探索元のpathを追加してあげることで、importすることができます。
※sys.pathとは探索してくれるpathが格納されているリストのことです。
__file__は実行場所から実行スクリプトファイル(この場合はsample.py)への相対パスなので、 どの場所からsample.pyを実行しても問題なくimportすることができます。

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

from utils.hoge import print_fuga

print_fuga()

同じ方法をnotebookで行おうとすると

通常のpythonファイルと同様の方法でnotebook上で実行しようとすると、以下のようなエラーが出てきてしまいます。
jupyter notebookでは、__file__が定義されていないようですね、、(そのままですが、、)

NameError: name '__file__' is not defined

解決方法

import sys
sys.path.append('..')

from utils.hoge import print_fuga

print_fuga()

これでも良いのかってほどの方法で解決してしまいました。
jupyter notebookは外から呼ばれることを想定されていないので、この方法で良いだろうって感じですね~。
ちなみに、sys.path.append(os.path.join(os.getcwd(), '..'))とかでも解決できるのですが、一番シンプルな方法にしました。

補足

通常のpythonファイルでsys.path.append('..')を使ってしまった場合、実行場所と実行スクリプトファイルの場所が異なるときにImport Errorが出てしまうので、注意してください。
jupyter notebookでは、実行場所と実行ファイルの場所が一致しているはずという前提のもと解決しているので、

参考

最後に

解決方法は拍子抜けするほど簡単でした、、
この問題に引っかかって解決するまで20分ぐらい時間がかかった気がするので共有します
はじめてこういうものを書いてみたので慣れていないのですが、こっちの方が良いよ等の意見があればコメント・twitter等でお待ちしております。