web-dev-qa-db-ja.com

pythonモジュールが複数回インポートされた場合、モジュールを最適化しますか?

大きなモジュールがコードのサブモジュールによってロードされる場合、モジュールを再度インポートするのではなく、その名前空間からモジュールを参照することに利点はありますか?

例:ReallyBigLibを多用するモジュールMyLibがあります。 MyLibをインポートするコードがある場合、そのようにモジュールを掘り出す必要があります

import MyLib
ReallyBigLib = MyLib.SomeModule.ReallyBigLib

あるいは単に

import MyLib
import ReallyBigLib
46
JimB

Pythonモジュールはシングルトンと見なすことができます...何度インポートしても、初期化されるのは1回だけなので、次のようにすることをお勧めします。

import MyLib
import ReallyBigLib

インポートステートメントに関連するドキュメント:

https://docs.python.org/2/reference/simple_stmts.html#the-import-statement

モジュールの名前がわかれば(特に指定がない限り、「モジュール」という用語はパッケージとモジュールの両方を指します)、モジュールまたはパッケージの検索を開始できます。最初にチェックされるのはsys.modulesで、これは以前にインポートされたすべてのモジュールのキャッシュです。モジュールがそこで見つかった場合は、インポートのステップ(2)で使用されます。

インポートされたモジュールは sys.modules にキャッシュされます:

これは、モジュール名をすでにロードされているモジュールにマップする辞書です。これを操作して、モジュールのリロードやその他のトリックを強制することができます。このディクショナリからモジュールを削除することは、対応するモジュールオブジェクトでreload()を呼び出すことと同じではないことに注意してください。

66
Toni Ruža

他の人が指摘しているように、Pythonは、インポートされたすべてのモジュールの内部リストを保持します。モジュールを初めてインポートするとき、モジュール(スクリプト)は独自の名前空間で実行されます最後まで、内部リストが更新され、インポートステートメントの後も実行が続行されます。

このコードを試してください:

   # module/file a.py
   print "Hello from a.py!"
   import b

   # module/file b.py
   print "Hello from b.py!"
   import a

ループはありません。キャッシュルックアップのみがあります。

>>> import b
Hello from b.py!
Hello from a.py!
>>> import a
>>>

Pythonの美しさの1つは、名前空間でスクリプトを実行するためにすべてがどのように発展するかです。

36
Charles Merriam

実質的な違いはありません。大きなモジュールがすでにロードされている場合、2番目の例の2番目のインポートは、現在の名前空間に「ReallyBigLib」を追加する以外は何もしません。

8

警告:Pythonは、モジュールが2回初期化されないことを保証しません。私はそのような問題に苦労しました。議論を参照してください: http://code.djangoproject.com/ticket/ 819

6
Munhitsu

インポートされたモジュールの内部レジストリはsys.modulesディクショナリであり、モジュール名をモジュールオブジェクトにマップします。そこを見ると、現在インポートされているすべてのモジュールを確認できます。

sys.modulesを使用してモンキーを作成することで、(必要に応じて)いくつかの便利なトリックを引き出すこともできます。たとえば、他のモジュールからインポートできる疑似モジュールとして独自のオブジェクトを追加します。

3
babbageclunk

パフォーマンス的にも同じです。 PythonにはまだJITコンパイラはありません。

0
Marko