Las mejores prácticas para la carga perezosa de módulos de Python

Ocasionalmente quiero cargar módulos perezosos en Python. Por lo general, porque quiero mantener bajos los requisitos de tiempo de ejecución o tiempos de inicio y dividir el código en submódulos sería engorroso. Un caso de uso típico y mi implementación actualmente preferida es la siguiente:

jinja2 = None class Handler(...): ... def render_with_jinja2(self, values, template_name): global jinja2 if not jinja2: import jinja2 env = jinja2.Environment(...) ... 

Me pregunto: ¿hay una forma canónica / mejor de implementar la carga de módulos perezosos?

No hay ninguna razón para que realice un seguimiento de las importaciones de forma manual: la VM mantiene una lista de módulos que ya se han importado, y cualquier bash posterior de importar ese módulo da como resultado una búsqueda rápida de dictados en sys.modules y nada más.

La diferencia entre tu código y

 def render_with_jinja2(self, values, template_name): import jinja2 env = jinja2.Environment(...) 

es cero: cuando jinja2 ese código, si jinja2 no se ha importado, entonces se importa. Si ya lo ha sido, la ejecución continúa.

 class Handler(...): ... def render_with_jinja2(self, values, template_name): import jinja2 env = jinja2.Environment(...) ... 

No hay necesidad de almacenar en caché el módulo importado; Python ya hace eso.

Las otras respuestas han cubierto los detalles reales, pero si estás interesado en una biblioteca de carga lenta , echa un vistazo a apipkg, que es parte del paquete py ( py.test fame).