Я пытаюсь написать декоратор, который проверяет наличие определенных пакетов c перед использованием функции.
В приведенном ниже примере numpy
не должно выдавать ошибку, но non_existent_test_package
должно информировать пользователя о том, что ему необходимо установить пакеты для использования этой функции. Дело в том, чтобы уменьшить зависимости.
ОБНОВЛЕНИЕ, основанное на предложении @ henry-harutyunyan
import numpy as np
import importlib
def check_available_packages(packages):
if isinstance(packages,str):
packages = [packages]
packages = np.asarray(sorted(set(packages)))
def wrapper(func):
installed = list()
for package in packages:
try:
globals()[package] = importlib.import_module(package)
installed.append(True)
except ImportError:
installed.append(False)
installed = np.asarray(installed)
assert np.all(installed), "Please install the following packages to use this functionality:\n{}".format(", ".join(map(lambda x: "'{}'".format(x), packages[~installed])))
return func
return wrapper
@check_available_packages(["numpy"])
def f():
print("This worked")
@check_available_packages(["numpy", "non_existent_test_package"])
def f():
print("This shouldn't work")
# ---------------------------------------------------------------------------
# AssertionError Traceback (most recent call last)
# <ipython-input-222-5e8224fb30bd> in <module>
# 23 print("This worked")
# 24
# ---> 25 @check_available_packages(["numpy", "non_existent_test_package"])
# 26 def f():
# 27 print("This shouldn't work")
# <ipython-input-222-5e8224fb30bd> in wrapper(func)
# 15 installed.append(False)
# 16 installed = np.asarray(installed)
# ---> 17 assert np.all(installed), "Please install the following packages to use this functionality:\n{}".format(", ".join(map(lambda x: "'{}'".format(x), packages[~installed])))
# 18 return func
# 19 return wrapper
# AssertionError: Please install the following packages to use this functionality:
# 'non_existent_test_package'
Теперь кажется, что декоратор проверяет, существуют ли пакеты во время выполнения, а не когда фактически вызывается функция. Как я могу настроить этот код?