あるパッケージが入っているかどうかを確認する方法にはpkgutilsというモジュールが便利だったので、使い方について備忘録的にまとめる。

環境

import sys

print(sys.version)

3.9.13 | packaged by conda-forge | (main, May 27 2022, 17:01:00)
[Clang 13.0.1 ]

使い方

標準ライブラリなのでpipやcondaによるインストールは不要。

import pkgutil

pkgutil.iter_modules

importできるものの一覧を取得するためにはpkgutil.iter_modulesメソッドを使用する。

pkgutil.iter_modules()

<generator object iter_modules at 0x107c9e970>

Generatorなのでfor文などで取り出すことができる。

for module in pkgutil.iter_modules():
    pass

pkgutil.ModuleInfo

モジュールの情報が入っているオブジェクト。基本的には.nameしか使用しないと思うのでこれだけメモ。

pkgutil.ModuleInfo.name

モジュールの名前が取り出せる。

module.name

'zmq'

たとえば特定の名前を持ったモジュールがあるかどうかを判定したい場合は以下のように書ける。

def exist_module(module_name: str) -> bool:
    for _module in pkgutil.iter_modules():
        if _module.name == module_name:
            return True
    else:
        return False

exist_module("pandas")

True

使用例

tqdmというプログレスバーを表示するモジュールがある。(参考: tqdmでプログレスバーを表示させる - Qiita

プログレスバーは必須ではないのでrequirementsに入れたくはないが、他のモジュールの依存関係的に入っているのであれば使用したいといったケース。

pkgutilを使用せずにtry...exceptで以下のように書くこともできるが、エラーハンドリング的にあまり望ましくない。

try:
    from tqdm import trange

    _range = trange
except ModuleNotFoundError as e:
    _range = range

pkgutilを使用して書き換えると以下のように書ける。

if exist_module("tqdm"):
    from tqdm import trange

    _range = trange
else:
    _range = range

先ほど定義したexist_module関数を使用した。

for i in _range(10):
    print(i)

100%|██████████| 10/10 [00:00<00:00, 184771.10it/s]

0
1
2
3
4
5
6
7
8
9

参考