LoginSignup
1
5

More than 3 years have passed since last update.

【日記】Pythonで上位階層のモジュールを力技によりimportさせたい

Last updated at Posted at 2019-07-09

※2019年07月18日:もっと有用な方法を続編の記事にて紹介しています→Pythonの自作モジュールをimportしたいならsys.pathを設定しよう

Pythonは自作のスクリプトでもモジュールとして別ファイルから読み込んで使うことができます。便利ですね。
公式ドキュメント → 6. モジュール (module)

基本的には(?)同階層や下位階層に存在するファイルからモジュールを読み込んで使うようです。
しかし、上位階層にあるモジュールを普通に読み込もうとするとエラーになります。
出力されるエラー内容は Attempted relative import beyond top-level package です。
スクリプト自身が存在する階層を、最上位のルート階層としてそれぞれ解釈するという挙動をしているのが原因のようですね。

こういう階層構造があるとする.txt
最上位フォルダ
├ 上位フォルダ
│ ├ 下位フォルダ
│ │ └ C.py
│ ├ A.py
│ └ B.py
└ D.py
A.py
from B import hoge # 同階層。出来る
from .下位フォルダ.C import foo # 下位階層。出来る
from ..D import bar # `..`は上位階層を示すらしい。なのに出来ない。出来ない。出来ない。出来ない。

しかし、これは各階層がパッケージ化(?)されていれば上位階層でも読み込めるんだそうです。
階層をパッケージ化するための要件はよくわかっていないんですが、とりあえず__init__.pyという名前の空ファイルを全階層に置いておけば良いという理解で私は解決しました。

つまりこういうことです.txt
最上位フォルダ
├ 上位フォルダ
│ ├ 下位フォルダ
│ │ ├ __init__.py # 追加
│ │ └ C.py
│ ├ __init__.py # 追加
│ ├ A.py
│ └ B.py
├ __init__.py # 追加
└ D.py

ウッソだろお前wwwwって目を疑いたくなるような光景ですが、事実これで上手くいったので……って書こうとしたらうまく行ってませんでした。とてもつらい。いや、やっぱり上手くいきました。う~~ん??????
上手くいったときは、最上位階層でターミナルを開いて、py -m スクリプト.pyの形式で実行しました。この辺り関係あるかも。

とまあ、最後よく分かんなくなっちゃいましたけど、このように__init__.pyさえ置いておけば、先ほどのA.pyの記述のままで上位階層のモジュールも読むことができるようになります。なるみたいなんです。

ホントは同階層か下層に配置してキレイになるようなパッケージの設計をすべきなんでしょうけど、今日のところはとりあえずこれで。

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5