Pythonモジュールがインポートされているかどうかを確認するにはどうすればよいですか?


91

コードのどこかにモジュールをインポートしたかどうかを確認するにはどうすればよいですか?

 if not has_imported("somemodule"):
     print('you have not imported somemodule')

すでにモジュールをインポートしたかどうかを確認したいのは、プログラムを台無しにすることがあるため、インポートしたくないモジュールがあるためです。


raise SystemError()インポートしたくないモジュールの上部に(または選択した他の例外を)配置するだけです。あなたがいる場合、実際にどこかにそれをインポートし、あなたのプログラムは、トレースバックをスローして終了します。
larsks 2015年

とにかく、モジュールをインポートするだけでプログラムが台無しになるのはどうしてですか?あまり聞こえないでしょう。
ビルウッダー2015年

1
@BillWoodger:おそらく、そのモジュールは、変更したくないグローバル状態を変更します。
MartijnPieters

@MartijnPietersYoiks。そして、インポートはとてもニュートラルに聞こえます。
ビルウッダー2015年

回答:


122

sys.modules辞書でモジュール名をテストします。

import sys

modulename = 'datetime'
if modulename not in sys.modules:
    print 'You have not imported the {} module'.format(modulename)

文書から:

これは、モジュール名をすでにロードされているモジュールにマップする辞書です。

importステートメントは2つのことを行うことに注意してください

  1. モジュールが以前にインポートされたことがない場合(==に存在しないsys.modules)、モジュールがロードされ、に追加されsys.modulesます。
  2. モジュールオブジェクトまたはモジュール名前空間のメンバーであるオブジェクトを参照する現在の名前空間内の1つ以上の名前をバインドします。

式はmodulename not in sys.modules、ステップ1が実行されたかどうかをテストします。手順2の結果をテストするには、importさまざまなオブジェクトを参照するためにさまざまな名前を設定するため、使用された正確なステートメントを知る必要があります。

  • import modulename セット modulename = sys.modules['modulename']
  • import packagename.nestedmoduleセットpackagename = sys.modules['packagename'](追加する追加レベルの数に関係なく)
  • import modulename as altname セット altname = sys.module['modulename']
  • import packagename.nestedmodule as altname セット altname = sys.modules['packagename.nestedmodule']
  • from somemodule import objectname セット objectname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulenameセットnestedmodulename = sys.modules['packagename.nestedmodulename'](このインポートの前nestedmodulenamepackagename名前空間に名前が付けられたオブジェクトがなかった場合のみ、ネストされたモジュールの追加の名前がこの時点で親パッケージの名前空間に追加されます)
  • from somemodule import objectname as altname セット altname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulename as altnameセットaltname = sys.modules['packagename.nestedmodulename'](このインポートの前nestedmodulenamepackagename名前空間に名前が付けられたオブジェクトがなかった場合のみ、ネストされたモジュールの追加の名前がこの時点で親パッケージの名前空間に追加されます)

インポートされたオブジェクトがバインドされた名前が特定の名前空間に存在するかどうかをテストできます。

# is this name visible in the current scope:
'importedname' in dir()

# or, is this a name in the globals of the current module:
'importedname' in globals()

# or, does the name exist in the namespace of another module:
'importedname' in globals(sys.modules['somemodule'])

これは、名前が存在する(バインドされている)ことを通知するだけであり、特定のモジュールまたはそのモジュールのオブジェクトを参照している場合は通知しません。それ以降sys.modules、名前が完全に別の名前に設定されていることを除外する必要がある場合は、そのオブジェクトをさらに内省したり、で使用可能なオブジェクトと同じオブジェクトであるかどうかをテストしたりできます。


1
これは、関数内で必要なパッケージをチェックするための最良の方法ですか?つまり、一部の関数にはnumpyパッケージが必要だとしましょう-import sys関数内でインポートされたことを確認するのに最適ですか?「最良」とはimport sys、関数が呼び出されるたびに呼び出されるパフォーマンスへの影響という意味です。ありがとう
交絡

@Confoundedは、心配な場合は関数の外にsysをインポートするだけです。それimport sysは決して高価ではありません。sys常に存在し、デフォルトではすでにロードされています。ただし、オプションのパッケージの場合:パッケージをインポートするだけです。ImportErrorパッケージがインストールされていない場合は例外をキャッチし、インポートが成功したときにインストールされていることを示すフラグを設定します。その後、フラグを使用して、オプションの依存関係の使用を通知できます。
MartijnPieters

@Confoundedこのname in sys.modulesテストは、をインポートしたくない場合にのみ役立ちます。
MartijnPieters

24

受け入れられたsys.modulesの回答に、インポート時にモジュールの名前を変更する際に注意する1つの警告を追加します。

>>> import sys
>>> import datetime as dt
>>> 'dt' in sys.modules
False
>>> 'datetime' in sys.modules
True

18

sys.modulesを使用して、モジュールがインポートされているかどうかをテストします(例としてunicodedataを使用しています)。

>>> import sys
>>> 'unicodedata' in sys.modules
False
>>> import unicodedata
>>> 'unicodedata' in sys.modules
True

5

sys.modules インタプリタの現在のインスタンスのどこかで使用されているすべてのモジュールが含まれているため、他のPythonモジュールにインポートされた場合に表示されます。

dir() 名前が現在の名前空間で定義されているかどうかを確認します。

2つの組み合わせは、それぞれの組み合わせよりも安全であり、copy自分で定義しない限り機能します。

if ('copy' in sys.modules) and ('copy' in dir()):

0
if "sys" not in dir():
  print("sys not imported!")

これは、モジュールが現在の名前空間にインポートされたかどうかのみをチェックします。また、sysだけではなく、モジュール、何もすることができます。
vaultah 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.