![](/img/trans.png)
[英]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.