1. ホーム
  2. パイソン

[解決済み】pythonのモジュールが存在するかどうかをインポートせずに確認する方法

2022-04-18 22:30:25

質問

Pythonモジュールが存在するかどうかを、インポートせずに知りたいのですが。

存在しないかもしれないものをインポートする(私が望むものではない)。

try:
    import eggs
except ImportError:
    pass

解決方法は?

Python2

python2 で import が何かを見つけることができるかどうかを確認するには、次のようにします。 imp

import imp
try:
    imp.find_module('eggs')
    found = True
except ImportError:
    found = False

ドット付きインポートを見つけるには、さらに工夫が必要です。

import imp
try:
    spam_info = imp.find_module('spam')
    spam = imp.load_module('spam', *spam_info)
    imp.find_module('eggs', spam.__path__) # __path__ is already a list
    found = True
except ImportError:
    found = False

を使用することもできます。 pkgutil.find_loader (python3の部分とほぼ同じ)

import pkgutil
eggs_loader = pkgutil.find_loader('eggs')
found = eggs_loader is not None

Python3

Python3 ≤ 3.3

を使用する必要があります。 importlib , どうやったかというと

import importlib
spam_loader = importlib.find_loader('spam')
found = spam_loader is not None

私の予想では、そのためのローダーが見つかれば、それは存在します。 また、もう少しスマートに、受け入れるローダーをフィルタリングすることもできます。 例えば

import importlib
spam_loader = importlib.find_loader('spam')
# only accept it as valid if there is a source file for the module - no bytecode only.
found = issubclass(type(spam_loader), importlib.machinery.SourceFileLoader)

Python3 ≧ 3.4

Python3.4では importlib.find_loader Python ドキュメント は非推奨となり、代わりに importlib.util.find_spec . 推奨される方法は importlib.util.find_spec . のような他のものがあります。 importlib.machinery.FileFinder これは、特定のファイルを読み込む場合に便利です。 これらの使い方を理解することは、この記事の範囲外です。

import importlib
spam_spec = importlib.util.find_spec("spam")
found = spam_spec is not None

これは相対的なインポートでも動作しますが、インポートする際に開始点を指定する必要があります。 パッケージを使用することもできます。

import importlib
spam_spec = importlib.util.find_spec("..spam", package="eggs.bar")
found = spam_spec is not None
spam_spec.name == "eggs.spam"

このようなことをする理由があることは確かですが、それが何であるかはわかりません。

警告

サブモジュールを探そうとすると、親モジュールをインポートします ( すべて 上記のメソッドのうち)!

food/
  |- __init__.py
  |- eggs.py

## __init__.py
print("module food loaded")

## eggs.py
print("module eggs")

were you then to run
>>> import importlib
>>> spam_spec = importlib.find_spec("food.eggs")
module food loaded
ModuleSpec(name='food.eggs', loader=<_frozen_importlib.SourceFileLoader object at 0x10221df28>, origin='/home/user/food/eggs.py')

この問題を回避するためのコメント歓迎

謝辞

  • インポートライブのための@rvighne
  • python3.3+ のデプリケート化については @lucas-guido を参照してください。 find_loader
  • pkgutils.find_loader の python2.7 での挙動を修正した @enpenax です。