TransWikia.com

Python importについて。外部ファイル読み込み

スタック・オーバーフロー Asked by nipopo on December 5, 2020

外部ファイルを読み込んで使用したいのですがうまくいきません。ご教示おねがいします。

環境
CentOS7
Python3.7
Django2

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 aaimport aa に変更すると python bb.py でも動きます

ここで質問なのですが、Djangoにおいても、ローカルにおいても同じコードでbb.pyを動かしたいのですがどうすればよいのでしょうか?
ご教示お願いいたします。

One Answer

「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で動くかどうかわかりませんが。

Answered by katsuko on December 5, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP