質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
import

自身のプラットフォーム・プログラム・データセットに対して、外部ソースを取り込むプロセスをimportと呼びます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

5012閲覧

Pythonの循環importが分からないです、助けてください

mmtaro000

総合スコア15

import

自身のプラットフォーム・プログラム・データセットに対して、外部ソースを取り込むプロセスをimportと呼びます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

3クリップ

投稿2020/10/22 08:50

前提・実現したいこと

プログラム実行結果の違いが判らない

発生している問題・エラーメッセージ

循環importの仕組みが分からなったので簡単なプログラムを使って実行したのですが、分からない部分がありました

該当のソースコード

test1.py

python

1import test_2 2 3test1num = 100 4ans = test_2.calc() 5a=ans 6print('test1:a = ', ans)

test_2.py

import test_1 test2num = 10 a = 0 def calc(): a = test_1.test1num +test2num return a print("test2 :a = ", a)

上記の二つのプログラムを同じ階層に配置し、それぞれを実行してみました

試したこと

それぞれのプログラムごとに実行したところ異なる結果が得られました。

test1を実行した場合

Traceback (most recent call last): File "c:\VSCodeProject\Project Files\Python\test1.py", line 1, in <module> import test2 File "c:\VSCodeProject\Project Files\Python\test2.py", line 1, in <module> import test1 File "c:\VSCodeProject\Project Files\Python\test1.py", line 4, in <module> ans = test2.calc() AttributeError: partially initialized module 'test2' has no attribute 'calc' (most likely due to a circular import)

test2.pyを実行した場合

test2 :a = 0 test1:a = 110 test2 :a = 0

どちらも互いのプログラムをimportしているのに対し、test2.pyのみ正常に実行されました。また、test2.pyではcalc()を呼び出していないにもかかわらず計算されて結果が表示されました。何が原因なのか教えていただきたいです。

補足情報

VSCodeでPython3.8.3を使用しました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

toast-uz

2020/10/22 13:29

「互いのプログラムをimport」した目的は何でしょうか?
mmtaro000

2020/10/22 13:39

大学の講義で使用してるプログラムで、ファイルA内でのみ定義されている変数をファイルBの関数の引数としているので、AにはBの関数を使用するためにimportし、BではAで定義されている変数を取得するためにimportしているためこのような状況になってしまいました。
guest

回答3

0

実行順については TakaiY様の回答通りです。

質問者様のやりたい動作にするには、if __name__ == "__main__"を使います。
参考: Pythonのif name == "main" とは何ですか?

具体的には以下のようになり、他のモジュールからimportされた際に実行させたくない範囲を、if __name__ == "__main__"の中に入れてしまいます。

test_1.py

Python

1import test_2 2 3test1num = 100 4 5if __name__ == '__main__': 6 ans = test_2.calc() 7 a=ans 8 print('test1:a = ', ans)

test_2.py

Python

1import test_1 2test2num = 10 3a = 0 4def calc(): 5 a = test_1.test1num +test2num 6 return a 7 8if __name__ == '__main__': 9 print("test2 :a = ", a)

test_1.pyを実行

test1:a = 110

test_2.pyを実行

test2 :a = 0

投稿2020/10/22 13:56

toast-uz

総合スコア3266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mmtaro000

2020/10/22 16:45

ありがとうございます!
guest

0

ちょうど同じような内容の話をQiitaに書いたので、そちらを参考にして下さい。

この話を理解するには、以下のPythonの仕様を把握する必要があります。(元の記事より引用)

  • import文は、そのモジュールのスクリプトを実行する。
  • モジュールAの中でモジュールBをimportされた場合、モジュールAのそれ以降の処理はモジュールBの処理が終わってから実行される。
  • importされたモジュールオブジェクトは、sys.modulesにモジュール名をキーとして保存され、2回目以降にimportされた場合は、sys.modulesに保存されたオブジェクトを返すだけで、モジュールのスクリプトの処理は実行されることはない。
  • 最初に起動するスクリプトは、「__main__」というモジュール名になる。(python test_1.pyと実行した後に、import test_1とした際には、最初は「__main__」というモジュールとして、次に「test_1」というモジュールとして、2度実行される)

投稿2020/10/22 13:52

katsuko

総合スコア3538

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mmtaro000

2020/10/22 13:53

ありがとうございます!参考にしてみます!
guest

0

ベストアンサー

pythonのインタプリタはファイルの中身を順に実行するので、そのまま読めばどのようなことが起っているかわかるはずです。

test_1.py を実行

text

11. test_2.pyを読み込む 2 2. test_1.pyを読み込む 3 3. test_2.py は読込み済みなので飛ばす 4 (ただじ、途中までしか読んでない。「partially initialized module」 5 4. 変数を設定 6 5. test_2.calc() を呼び出す。 が、存在しない。 7 まだ読んでないところに書いてあるから

test_2.pyを実行

text

11. test_1.pyを読み込む 2 2. test_2.pyを読み込む 3 3. test_1.pyは読込み済みなので飛ばす 4 4. 変数定義 5 5. calc()の定義 6 6. printの実行(test2) 7 7. 変数定義 8 8. test_2.calc() の実行 定義済みなので実行できる。 9 9. printの実行(test1) 1010. 変数定義 1111. calc()の定義 1212. printの実行(test2)

こうなってます。

投稿2020/10/22 09:32

TakaiY

総合スコア13790

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mmtaro000

2020/10/22 13:42

つまりtest1.pyを先に実行するとimport test_2→import test_1→test1num=100という順番に実行されるため、calc()の定義にたどり着く前に先に呼び出してしまっているということですか?
TakaiY

2020/10/23 09:54

そうです
mmtaro000

2020/10/23 18:33

ありがとうございます。わかりやすい解説で助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問