Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

174
Views
¿Cómo puedo importar perezosamente un módulo en python?

Tengo clases que requieren dependencias para ser instanciadas, pero por lo demás son opcionales. Me gustaría importar perezosamente las dependencias y fallar al crear una instancia de la clase si no están disponibles. Tenga en cuenta que estas dependencias no son necesarias a nivel de paquete (de lo contrario, serían obligatorias a través de las herramientas de configuración). Actualmente tengo algo como esto:

 class Foo: def __init__(self): try: import module except ImportError: raise ModuleNotFoundError("...") def foo(self): import module

Debido a que este patrón de prueba/excepto es común, me gustaría abstraerlo en un importador perezoso. Idealmente, si el module está disponible, no necesitaré importarlo nuevamente en Foo.foo , por lo que me gustaría que el module esté disponible una vez que se haya importado en __init__ . Intenté lo siguiente, que llena globals() y no crea una instancia de la clase si numpy no está disponible, pero contamina el espacio de nombres global.

 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,])

Podría instanciar el módulo fuera de la clase y apuntar al módulo importado si la importación no falla, pero eso es lo mismo que el enfoque globals() . Alternativamente, lazy_import podría devolver el mod y podría llamarlo cada vez que se necesite el módulo, pero esto equivale a importarlo en todas partes como antes.

¿Hay una mejor manera de manejar esto?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Pandas en realidad tiene una función import_optional_dependency que puede ser un buen ejemplo ( enlace GitHub ) como se usa en SQLAlchemyEngine ( enlace GitHub )

Sin embargo, esto solo se usa durante la clase __init__ para obtener un error significativo ( raise ImportError(...) de forma predeterminada!) importar correctamente en cualquier lugar si existen, pero no funcionan o se prueban explícitamente o incluso son una importación local accidental)

Consideraría hacer algo similar, y no molestarme en tener un manejo especial o solo hacerlo en __init__ (y quizás solo en algunos casos en los que esté interesado en la versión, etc.) y, de lo contrario, simplemente importar donde sea necesario

 class Foo(): def __init__(self, ...): import bar # only tests for existence def usebar(self, value): import bar bar.baz(value)

Posiblemente podría asignar a una propiedad de la clase, pero esto puede causar algunos problemas o confusión (ya que la importación ya debería estar disponible en globals una vez importada)

 class Foo(): def __init__(self, ...): import bar self.bar = bar def usebar(self, value): self.bar.baz(value)
over 4 years ago · Santiago Trujillo Report

0

Le di una prueba rápida con un envoltorio, parece funcionar bien:

 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())

Editar: uno más avanzado que funciona con cualquier módulo y garantiza que sea un módulo en caso de que se haya configurado en otra cosa.

 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())
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!