Importar módulos de Python en el momento del uso

8

A menudo, en mis propias bibliotecas personales de Python, hago algo como esto:

class MyClass:

    # ...

    def plot(self):
        import someGraphicsLibrary as graphicslib
        graphicslib.plot(self.data)

La razón es que la inicialización someGraphicsLibrarylleva algo de tiempo, hasta unos segundos para una de las bibliotecas que uso. No siempre necesito trazar mis resultados cuando uso esta clase, por lo que tiene sentido no importarlo hasta el momento en que se usa, si es que lo hace.

Esto parece funcionar bien, pero no creo que lo haya visto en el código de otra persona. Entonces mi pregunta es simplemente si esto se considera una buena práctica. ¿Hay alguna trampa oculta que se puede esperar al hacer las cosas de esta manera?

Nathaniel
fuente
1
Esto es simplemente una forma de carga diferida , que no es muy especial.
Doc Brown
1
Además de ser un poco feo, no hay una razón real por la que no puedas hacer esto. Y si la importación de la biblioteca lleva tanto tiempo, incluso hay una causa legítima para hacerlo. Me gustaría hacer esto raramente. La mayoría de las importaciones no deberían ser tan lentas.
Neil
@DocBrown No digo que sea especial, solo pregunto si se considera una buena / mala práctica en Python específicamente.
Nathaniel
@Nathaniel: parece haber una creencia supersticiosa en la existencia de "mejores prácticas" absolutas entre muchos desarrolladores, lo cual no tiene sentido, en mi humilde opinión, cualquier "práctica" tiene pros y contras, y lo que es bueno o malo solo puede evaluarse en el específico contexto. Su ejemplo anterior me parece razonable, es simple y claro, y el único inconveniente real es que es más difícil ver todas las dependencias de un módulo de un vistazo (que es el punto # 3 en la respuesta de Kevin). Entonces, si crees que la mejora del rendimiento vale la pena, entonces esta práctica es buena, si no, esta práctica es mala.
Doc Brown

Respuestas:

9

Esto no suele ser una buena práctica, por varias razones:

  1. La mayoría de las veces, el método será rápido, pero la primera vez que lo llame, será lento. Eso es mucho menos predecible que una importación al momento del inicio.
  2. Si la importación falla por varias razones, no lo sabrá hasta que llame al método en tiempo de ejecución.
  3. Es más difícil ver de qué módulos depende su módulo, porque no están listados en la parte superior del archivo.
  4. Si un módulo literalmente tarda "unos segundos" en importarse, puede estar haciendo demasiado en su lógica de tiempo de importación. La lógica del tiempo de importación generalmente debe hacer "lo suficiente" para que el módulo sea utilizable, y no debe crear objetos globales pesados. Ocasionalmente, tales objetos son necesarios, pero deben examinarse cuidadosamente.

Sin embargo, a veces esta es una buena idea, por ejemplo:

  1. Al implementar un tipo de matriz , es posible que deba usarlo numpyen su __array__()método. Pero es posible que no desee depender numpyde la otra funcionalidad de su módulo, por lo que es mejor importar numpydentro __array__()para evitar tomar la dependencia adicional cuando no es necesario. Esto no sufre los problemas 1 y 2 porque numpyya se importó una vez antes (¡es lo que llama __array__()en primer lugar!), Y no sufre el problema 3 porque numpyno es una dependencia "real" de su módulo.
  2. Antes de PEP 553 , un punto de interrupción tradicionalmente era la siguiente: import pdb; pdb.set_trace(). No desea colocarlo import pdben la parte superior del módulo porque el punto de interrupción es una línea de código temporal que se eliminará, y mover la importación muy lejos lo haría innecesariamente difícil. Esto estaba obsoleto cuando breakpoint()se agregó el incorporado , por lo que ahora no necesita una importación en línea.
Kevin
fuente
44
Olvidó mencionar que el ejemplo publicado por el OP se parece a uno que se ajusta al caso "Buena idea # 1" en su respuesta. Parece una clase o módulo que tiene una funcionalidad central que es independiente del trazado y podría usarse sin la biblioteca de gráficos.
Doc Brown
@DocBrown: MyClassno es un sustantivo significativo, así que creo que estás sacando conclusiones.
Kevin
Bueno, me tomé el tiempo de leer la publicación completa. Tal vez hice algunas conjeturas, pero veamos qué piensa el OP al respecto (y no me malinterpreten, su respuesta ya recibió un voto positivo de mi parte).
Doc Brown
El primer comentario de @Kevin Doc Brown es una interpretación correcta de mi publicación. (+1, esta es una respuesta útil.)
Nathaniel