質問: 外部ファイルを読み込んで、使用したいのですがうまくいきません。ご教示おねがいします。 環境 CentOS7 Python3.7 Djang2 tree .app1 |-aa.py 読み込まれるファイル |-bb.py 読み込むファイル aa.py ``` def hoge: print('hogehoge') ``` bb.py ``` from . import aa aa.hoge() ``` Djangoからだと確かにbb.pyで動くのですが python bb.pyをすると from . import aa ImportError: cannot import name 'aa' from '**main**' (bb.py) というエラーが出ます しかしbb.pyの from . import aa を import aa に変更すると python bb.py でも動きます ここで質問なのですが、 Djangoにおいても、ローカルにおいても同じコードでbb.pyを動かしたいのですが どうすればよいのでしょうか? ご教示お願いいたします。
回答: 「app1」ディレクトリと同じディレクトリに以下のような「run.py」を置いて、それを起動する、ではダメですか? ``` # coding: utf-8 import app1.bb ``` pythonのインポートシステムはちょいとややっこしいので、ちゃんと説明できるかわからないし、そもそもこれであっているかどうかもわかりません。 以下の話は、そのつもりで聞いてください。 「from . import aa」のような相対インポートは、同一パッケージ内のサブモジュール間でのみ使用できるようです。 もうちょっとわかりやすく(なっていないかもしれないけど)言うと、例えば ``` sys.path += ['.'] import app1.bb ``` とした場合、「app1」がパッケージとなり、その配下にある「aa.py」「bb.py」は「app1」パッケージのサブモジュール同士という関係になるので、「from . import aa」というインポートは可能になります。 しかし、 ``` sys.path += ['./app1'] import bb ``` とした場合、「bb」がパッケージとなるので、「aa.py」は別パッケージのモジュールと判断されます。 djangoは使った事がないのでよくわかりませんが、おそらく前者のパターンで「bb.py」がインポートされていのではないでしょうか。 もう一つ知っておきたい点として、「import aa」とした「bb.py」を「python bb.py」として実行するとなぜ成功するか。 これは、「aa.py」が「bb.py」と同じディレクトリにあるから、という事が**直接的な理由**ではありません。 1. 「python bb.py」と実行されると、「bb.py」の親ディレクトリが「sys.path」の先頭に追加される。 2. 「import aa」が実行された際、「sys.path」で示されたディレクトリ内にある「aa」パッケージを探して、インポートされる。 という手順が踏まれるため、**結果的に**「bb.py」と同じディレクトリにある「aa.py」がインポートされます。 以上のことを踏まえて考えれば、「bb.pyを直接実行した際に相対インポートが使えない」という理由になるのではないでしょうか。 なんてつらつら書きましたが、書いている間にもう一つ対策を考えました。 ``` if __name__ == '__main__': import aa else: from . import aa ``` でもいいんじゃないでしょうか。 djangoで動くかどうかわかりませんが。