2009-11-28 6 views
18

非常に大きなアプリケーションにいくつかの新しいコードを追加するという周期的なインポートの問題があります。どのファイルをどのファイルにインポートするかを追跡する方法はありますか?私は少し調べてpython traceコマンドを見つけましたが、主なPythonライブラリにはたくさんのアクティビティが表示されています。Pythonのインポートを追跡するにはどうすればいいですか

私は基本的には私のようなものが表示されますアプリを探しています:私はちょうど私のファイルのすべてに目を通すことができ

App1 >>imports>> App2,App3.method 
App2 >>imports>> App3,etc 

を、私はむしろない、それは大きなアプリだと思います。

答えて

11

あなたはPythonのモジュールの依存関係グラフを作るためにこれらのスクリプトのいずれかを使用できます。

+1

Snakefoodが私の望むものになった。しかし、より多くのファイルを扱うためにはマッサージが必要です。 – Jeff

+0

@Jeff:はい、セットアップには少し時間がかかり、ドキュメントを読むことは必須です。私はあなたがそれを働かせることができてうれしいです! – unutbu

-2

モジュールを再度インポートする前にインポートされているかどうかをチェックするので、Pythonで循環インポートを取得することはできません。インポートを何回呼び出しても、モジュールは一度しかインポートできません。 http://groups.google.com/group/comp.lang.python/browse_thread/thread/1d80a1c6db2b867c?pli=1から

輸入は本当に 非常に簡単です。次のことを覚えておいてください。

'import'と 'xxx import yyy'は 実行文です。実行中のプログラムが 行に達すると、 が実行されます。

モジュールはsys.modulesにない場合、 は、インポートはsys.modulesに新しいモジュール エントリを作成し、モジュールに コードを実行します。実行が完了するまで 呼び出し元モジュール に制御を戻しません。

モジュールはsys.modules に存在しない場合、インポートは、単にそれが実行 を完了した モジュールか否かということ返します。そのため、 循環インポートが、部分的に空であると思われるモジュール を返す可能性があります。

最後に、実行中のスクリプトは、自身の名の下 スクリプトが __main__とは無関係の新しいモジュールを作成しますインポート、 に__main__という名前のモジュールを実行します。

モジュールをインポートすると、 は驚くことはありません。

+6

を見てみる必要があります。無限にループすることはありませんが、2つのファイルが相互にインポートされるため、必要に応じて関数が定義されていない問題が発生する可能性があります。 –

+3

Pythonでの循環インポートは、モジュールからアイテムをインポートし、他のモジュールからインポートするときにのみ問題になります。 A.py:インポートB B.py:インポートA 参照がインポートされた実際の実行/使用に延期されるため、相互に巡回インポートしても問題は発生しませんアイテム。これは、問題を引き起こす定義されていない別のモジュール(つまり、インポート時に参照を要求する)からアイテムをリクエストするときだけです。 –

9

python -vを使用してプログラムを実行してください。それは輸入の順序を追跡するでしょう。

もう1つの選択肢はpylintです。これは、周期的なインポートを含むあらゆる種類の問題を警告します。

+3

私はこの-vオプションを、uwsgiの下でpythonを実行しているときに使いたいと思っていました。私はこれを私のuwsgi iniファイルに追加してしまいました。 'env = PYTHONVERBOSE = 1' そして、出力は通常のuwsgiログファイルで指定されたものに入ります。 –

14

をここです簡単な(そして少し初歩的な;-)モジュール名の用語で「何をインポートしようとしている人」トレースする方法:

import inspect 
import __builtin__ 
savimp = __builtin__.__import__ 

def newimp(name, *x): 
    caller = inspect.currentframe().f_back 
    print name, caller.f_globals.get('__name__') 
    return savimp(name, *x) 

__builtin__.__import__ = newimp 

与える、例えば()tracimp.pyとしてこれを保存した:

$ python -c 'import tracimp; import email; import sys; import email.mime' 
email __main__ 
sys email 
email.mime email 
sys __main__ 
email.mime __main__ 

ご覧のとおり、__import__を「ラッピングする」という特有の特徴の1つは、インポートするモジュールが既にsys.modulesにあるという事実によって消されないということです。これは世話を__import__のジョブの1つとしているためです、私たちのラッパーは両方のモジュール "最初にロードされて"呼び出されますは、以前にすでにインポートされているため、sys.modulesからフェッチされます。これは、循環インポートを診断しようとしているときには本当に便利です(インポートされたインポータという2つのモジュール名でエッジが識別される有向グラフのループを見つけることに至ります。出力ライン)。

たぶん後半
関連する問題