利用しているPythonのバージョンは3.6です。
もし間違った記述等があれば、コメントで指摘していただけるとうれしいです。
PEP8の違反内容
このようなディレクトリ構成で、scripts/execute.py
からlib
配下の自作モジュールを読み込みたいとします。
.
├──scripts
│ └── execute.py
└──lib
└── my_module.py
当初、execute.py
を次のように記述し、sys.path
にファイルを追加することで対処しようとしました。
import pandas as pd
import sys
sys.path.append('../lib')
import my_module
# (以下略)
ところが、これはPythonのコーディング規約であるPEP8(日本語訳)に違反しているため、flake8等を利用している場合は次のツッコミが入ります。
E402 module level import not at top of file
日本語訳の該当箇所を引用しておきましょう。
import文 は常にファイルの先頭、つまり モジュールコメントや docstring の直後、そしてモジュールのグローバル変数や定数定義の前に置くようにします。
環境変数PYTHONPATHを設定して解決
ちょうど、Stackoverflowに同じ趣旨の質問がありました。
この中に、いくつかの方法が回答されており、環境変数PYTHONPATH
にディレクトリを追加する方法が本質的な解決方法のように思えました。(以下のリンクが紹介されていました)
(他にも、以下のような方法も紹介されていましたが、正直私には小狡いハックにしか見えません。)
- パスの読み込み処理を記述した
pathmagic.py
というファイルを用意し、それをimportする方法 - try~except文で囲む方法
また、日本語の質問サイトであるteratailにも似た質問の回答がありました。Sphinxのコミッターの清水川さんの回答なので信憑性は高そうです。
sys.path をスクリプト内で調整することはあまり推奨されません。
色々なところで使いたいライブラリを置いているディレクトリが固定で、そのライブラリをimportしたいのであれば、環境変数 PYTHONPATH を設定する方法があります。
というわけで、PYTHONPATHにlib
ディレクトリを追加して対処しました。毎回利用する場合はbash_profile
にでも書いておきます。
export PYTHONPATH="${PYTHONPATH}:/libディレクトリのフルパス/lib"
これにより、execute.py
からsys.path
関連の記述を削除できました。
import pandas as pd
import my_module
# (以下略)
環境変数PYTHONPATHについて
本題とはずれるのですが、ここで「ライブラリ名と自作のモジュール名がバッティングした場合はどうなるの?」ということが気になって調べてみました。
こういうときは公式ドキュメントを読みましょう。公式のPythonチュートリアルの中に以下のような記述があります。
spam という名前のモジュールをインポートするとき、インタープリターはまずその名前のビルトインモジュールを探します。見つからなかった場合は、 spam.py という名前のファイルを sys.path にあるディレクトリのリストから探します。 sys.path は以下の場所に初期化されます:
- 入力されたスクリプトのあるディレクトリ (あるいはファイルが指定されなかったときはカレントディレクトリ)。
- PYTHONPATH (ディレクトリ名のリスト。シェル変数の PATH と同じ構文)。
- インストールごとのデフォルト。
どうやら、PYTHONPATHにあるもののほうが優先されるようです。実際に試してもそのような挙動でした。