Módulos de Python con nombres idénticos (es decir, reutilizando nombres de módulos estándar en paquetes)

Supongamos que tengo un paquete que contiene módulos:

SWS/ __init.py__ foo.py bar.py time.py 

y los módulos necesitan referirse a funciones contenidas entre sí. Parece que tengo problemas con mi módulo time.py ya que hay un módulo estándar que lleva el mismo nombre.

Por ejemplo, en el caso de que mi módulo foo.py requiera tanto mi SWS.time como los módulos de time estándar de Python, tengo problemas ya que el intérprete buscará dentro del paquete y encontrará mis módulos de time.py antes de encontrar el estándar. módulo de time .

¿Hay alguna manera de evitar esto? ¿Es esta una situación de no-no y no se deben reutilizar los nombres de los módulos?

Cualquier solución y opinión sobre la filosofía del paquete sería útil aquí.

Reutilizar nombres de funciones / clases / módulos / paquetes estándar nunca es una buena idea. Intenta evitarlo tanto como sea posible. Sin embargo, hay soluciones limpias para su situación.

El comportamiento que ve, al importar su SWS.time lugar de la time estándar, se debe a la semántica de la import en versiones antiguas de python (2.x). Para solucionarlo añade:

 from __future__ import absolute_import 

en la parte superior del archivo. Esto cambiará la semántica de import a la de python3.x, que son mucho más sensibles. En ese caso la statement:

 import time 

Sólo se referirá a un módulo de nivel superior. Por lo tanto, el intérprete no considerará su módulo SWS.time al ejecutar esa importación dentro del paquete, pero solo utilizará la biblioteca estándar.

Si un módulo dentro de su paquete necesita importar SWS.time , tiene la opción de:

  • Usando una importación relativa explícita :

     from . import time 
  • Usando una importación absoluta:

     import SWS.time as time 

Entonces, tu foo.py sería algo como:

 from __future__ import absolute_import import time from . import time as SWS_time 

Depende de la versión de Python que estés usando. Si su versión de Python específica es 2.4 o más antigua (en 2015, espero que no), entonces sí sería una mala práctica ya que no hay manera (sin hacks) de diferenciar los dos módulos.

Sin embargo, en Python 2.5+, creo que reutilizar nombres de módulos lib estándar dentro de un espacio de nombres de paquetes es perfectamente correcto; De hecho, ese es el espíritu de PEP328 .

A medida que la biblioteca de Python se expande, cada vez más módulos internos de paquetes existentes de repente se ocultan por accidente en los módulos de biblioteca estándar. Es un problema particularmente difícil dentro de los paquetes porque no hay manera de especificar a qué módulo se refiere. Para resolver la ambigüedad, se propone que foo siempre será un módulo o paquete accesible desde sys.path. Esto se llama una importación absoluta.

La comunidad python-dev eligió las importaciones absolutas como predeterminadas porque son el caso de uso más común y porque las importaciones absolutas pueden proporcionar toda la funcionalidad de las importaciones relativas (entre paquetes), aunque a costa de la dificultad al cambiar el nombre de las partes de los paquetes. en la jerarquía o al mover un paquete dentro de otro.

Debido a que esto representa un cambio en la semántica, las importaciones absolutas serán opcionales en Python 2.5 y 2.6 mediante el uso de from __future__ import absolute_import

SWS.time es lo mismo que el time y, como lector del código, espero que SWS.time no solo use el time , sino que lo extienda de alguna manera.

Entonces, si SWS.foo necesita importar SWS.time , entonces debería usar la ruta absoluta:

 # in SWS.foo # I would suggest renaming *within* # modules that use SWS.time so that # readers of your code aren't confused # with which time module you're using from SWS import time as sws_time 

O, debe usar una importación relativa explícita como en la respuesta de Bakuriu:

 # in SWS.foo from . import time as sws_time 

En el caso de que necesite importar el módulo de time SWS.time estándar dentro del módulo SWS.time , primero deberá importar la función futura (solo para Python 2.5+; Python 3+ lo hace de manera predeterminada):

 # inside of SWS.time from __future__ import absolute_import import time time.sleep(28800) # time for bed 

Nota: from __future__ import absolute_imports solo afectará a las declaraciones de importación dentro del módulo que la característica futura se importará y no afectará a ningún otro módulo (ya que sería perjudicial si otro módulo depende de las importaciones relativas).

Como han dicho otros, esta es generalmente una mala idea.

Dicho esto, si está buscando posibles soluciones, o una mejor comprensión del problema, le sugiero que lea las siguientes preguntas de SO:

  • Importación desde la biblioteca incorporada cuando existe un módulo con el mismo nombre

  • ¿Cómo acceder a un módulo de biblioteca estándar en Python cuando hay un módulo local con el mismo nombre?

Sí, realmente no hay una buena manera de evitarlo. Trate de no nombrar sus módulos como paquetes estándar. Si realmente quieres llamar a la time tu módulo, te recomiendo usar _time.py en _time.py lugar. Incluso si hubiera una manera de hacerlo, haría que su código fuera difícil de leer y confuso cuando se trataba de los 2 módulos de tiempo.