Pythonがエラーを報告 循環的なインポートが原因である可能性が高い Solution
<スパン これは、個々のPythonファイルが互いに参照し合うことによって引き起こされる循環参照問題が原因です。
解決方法 参照する必要のあるファイルを1つのファイルに分離し、一方的に参照されるようにする
Pythonで少し大きなプロジェクトを書くと、circular import、つまりcicular importの問題によくぶつかります。この投稿は、flaskで遭遇した問題をモデルにしています
cicular importが発生する理由と、pythonでimportファイルを使用する際にpythonが具体的に何をしているのかを説明します。
1. 循環型インポートの例
以前、循環型インポートの問題に遭遇したのですが、プロジェクトのファイル構成は大体以下のような感じでした。
flask_demo\
app\
auth\
__init__.py
__init__.py
run_server.py
app ディレクトリの __init__.py ファイルには、次のように記述されています。
from flask import Flask
from flask_login import LoginManager
def create_app():
app = Flask(__name__)
from app.auth import auth_bp
app.register_blueprint(auth_bp)
return app
app = create_app()
login_manager = LoginManager(app)
app/auth ディレクトリの __init__.py ファイルには、次のように記述されています。
from flask import Blueprint
from app import login_manager
# Register Blueprint
auth_bp = Blueprint('auth_bp', __name__)
最後に run_server.py ファイルを実行します。
from app import app
app.run()
今度は、flaskのWebアプリが正常に起動せず、以下のようなエラーが報告されます。
Traceback (most recent call last):
File "/Users/caoxin/work/python_project/flask_demo/run_server.py", line 10, in <module>
from app import app
File "/Users/caoxin/work/python_project/flask_demo/app/__init__.py", line 24, in <module>
app = create_app()
File "/Users/caoxin/work/python_project/flask_demo/app/__init__.py", line 17, in create_app
from app.auth import auth_bp
File "/Users/caoxin/work/python_project/flask_demo/app/auth/__init__.py", line 11, in <module>
from app import login_manager
ImportError: cannot import name 'login_manager' from 'app' (/Users/caoxin/work/python_project/flask_demo/app/__init__.py)
これは典型的なcicular importの問題で、これを解決するには、pythonでimportを使用する際にコードが実際にどのように動作するかをよく理解する必要があります。
2.インポート実行プロセス
ファイルをインポートするとき、pythonはまずそのファイルが以前にインポートされたことがあるかどうかを調べ、以前にインポートされたことがある場合は、再びインポートされることはありません。ですから、もしモジュールA
コード内でBモジュールがインポートされ、Aモジュールの中でBモジュールがインポートされると、pythonの実行順序は次のようになります。
- モジュールAの実行開始
- Aの実行がインポートBに到達すると、モジュールA以降のコードの実行を停止し、代わりにモジュールBのコードの実行を開始する
- モジュールBが最初からimport Aがあるところまで実行されると、この時点でpythonは はしません。 は戻ってAのコードの残りを実行し、Aモジュールを プロパティが初期化され、中断する前に はBモジュールに読み込まれます
上の例で分割してみましょう、app/
イニット
.py の create_app() メソッドで from auth import auth_bp を使用すると、app/ が壊れます。
イニット
.py が実行され、代わりに
auth/
イニット
ここで重要なのは、この時点でapp/
イニット
.py は app と login_manager の両方の属性で宣言されています。また、auth/
イニット
.py は再び app モジュールからのインポートを希望しています。
login_managerプロパティです。明らかに、ここでエラーが報告されます。これを解決するには、コード構造を変更して、auth/のlogin_managerプロパティが、以下のようになるようにする必要があるでしょう。
イニット
.py に到達する前に実行され、from app import
login_managerが実行された時点で、すでにappモジュールに定義されているため、以下のようになります。
from flask import Flask
from flask_login import LoginManager
login_manager = LoginManager() # Declare login_manager before the auth module runs
def create_app():
app = Flask(__name__)
login_manager.init_app(app)
from app.auth import auth_bp
app.register_blueprint(auth_bp)
return app
app = create_app()
Pythonがインポートするときにどのように動作するかを理解することで、この循環インポート問題を簡単に分析し解決することができるのです。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
ハートビート・エフェクトのためのHTML+CSS
-
HTML ホテル フォームによるフィルタリング
-
HTML+cssのボックスモデル例(円、半円など)「border-radius」使いやすい
-
HTMLテーブルのテーブル分割とマージ(colspan, rowspan)
-
ランダム・ネームドロッパーを実装するためのhtmlサンプルコード
-
Html階層型ボックスシャドウ効果サンプルコード
-
QQの一時的なダイアログボックスをポップアップし、友人を追加せずにオンラインで話す効果を達成する方法
-
sublime / vscodeショートカットHTMLコード生成の実装
-
HTMLページを縮小した後にスクロールバーを表示するサンプルコード
-
html のリストボックス、テキストフィールド、ファイルフィールドのコード例