[英]Python: How can I install a python module into a certain folder and import it
[英]How can I lazily import a module in python?
我有需要依赖项才能被实例化的类,但在其他方面是可选的。 我想懒惰地导入依赖项,如果 class 不可用,则无法实例化它们。 请注意,package 级别不需要这些依赖项(否则它们将通过 setuptools 强制执行)。 我目前有这样的事情:
class Foo:
def __init__(self):
try:
import module
except ImportError:
raise ModuleNotFoundError("...")
def foo(self):
import module
因为这种 try/except 模式很常见,所以我想将它抽象为一个惰性导入器。 理想情况下,如果module
可用,我不需要在Foo.foo
中再次导入它,所以我希望module
在__init__
中导入后可用。 我尝试了以下方法,如果numpy
不可用,它会填充globals()
并且无法实例化 class ,但它会污染全局命名空间。
def lazy_import(name, as_=None):
# Doesn't handle error_msg well yet
import importlib
mod = importlib.import_module(name)
if as_ is not None:
name = as_
# yuck...
globals()[name] = mod
class NeedsNumpyFoo:
def __init__(self):
lazy_import("numpy", as_="np")
def foo(self):
return np.array([1,2,])
如果导入没有失败,我可以在 class 之外实例化模块并指向导入的模块,但这与globals()
方法相同。 或者lazy_import
可以返回mod
,我可以在需要模块时调用它,但这无异于像以前一样在任何地方导入它。
有没有更好的方法来处理这个?
Pandas actually has a function import_optional_dependency
which may make a good example ( link GitHub ) as used in SQLAlchemyEngine
( link GitHub )
但是,这仅在 class __init__
期间使用以获得有意义的错误(默认为raise ImportError(...)
)或警告缺少或旧的依赖项(这可能是更实际的使用它,因为较旧或较新的依赖项可能如果它们存在,则可以在任何地方正确导入,但不能正常工作或被明确测试甚至是意外的本地导入)
我会考虑做类似的事情,要么不费心进行特殊处理,要么只在__init__
中进行(然后可能仅适用于您对版本感兴趣的少数情况等),否则只需在需要的地方导入
class Foo():
def __init__(self, ...):
import bar # only tests for existence
def usebar(self, value):
import bar
bar.baz(value)
有可能您可以分配给 class 的属性,但这可能会导致一些麻烦或混乱(因为一旦导入,导入应该已经在globals
中可用)
class Foo():
def __init__(self, ...):
import bar
self.bar = bar
def usebar(self, value):
self.bar.baz(value)
用包装器对其进行快速测试,似乎工作正常:
def requires_math(fn):
def wrapper(*args, **kwargs):
global math
try:
math
except NameError:
import math
return fn(*args, **kwargs)
return wrapper
@requires_math
def func():
return math.ceil(5.5)
print(func())
编辑:更高级的一个,适用于任何模块,并确保它是一个模块,以防它被设置为其他东西。
from types import ModuleType
def requires_import(*mods):
def decorator(fn):
def wrapper(*args, **kwargs):
for mod in mods:
if mod not in globals() or not isinstance(globals()[mod], ModuleType):
globals()[mod] = __import__(mod)
return fn(*args, **kwargs)
return wrapper
return decorator
@requires_import('math', 'random')
def func():
return math.ceil(random.uniform(0, 10))
print(func())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.