2012-05-08 14 views
9

Supongamos que tengo un paquete que contiene módulos:módulos de Python con nombres idénticos (es decir, la reutilización de los nombres de módulo estándar en paquetes)

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

y los módulos necesitan para referirse a funciones contenidas en el uno al otro. Parece que tengo problemas con mi módulo time.py ya que hay un módulo estándar que recibe el mismo nombre.

Por ejemplo, en el caso de que mi módulo de foo.py requiere tanto de mis SWS.time y el estándar time módulos de Python, que se meten en problemas ya que el intérprete se verá en el interior del paquete y encontrar mis módulos time.py antes de que entre a través del módulo estándar time .

¿Hay alguna forma de evitar esto? ¿Es esta una situación de no-no y no deberían reutilizarse los nombres de los módulos?

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

+2

Creo que es bastante obvio que no debe volver a utilizar nombres de módulo de python estándar. Solo está buscando problemas. – Cryptite

+3

¿Por qué es obvio? MikeWyatt

+0

Mire httplib/httplib2 y urllib/urllib2. Crea un mundo de bibliotecas más feo, pero es preferible mencionar colisiones y comportamientos indeterminados. –

Respuesta

10

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 alternativas a su situación.

El comportamiento que se observa, la importación de su SWS.time en lugar de la stdlib time, se debe a la semántica de import en versiones antiguas de pitón (2.x). Para solucionarlo, agregue:

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 sensatas. En ese caso, la instrucción:

import time 

Se referirá únicamente a un módulo de nivel superior. Entonces el intérprete va a no considere su módulo SWS.time al ejecutar esa importación dentro del paquete, pero solo usará la biblioteca estándar.

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

  • El uso de un explícita relativa de las importaciones:

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

    import SWS.time as time 
    

lo tanto, su foo.py sería algo así como:

from __future__ import absolute_import 

import time 

from . import time as SWS_time 
+2

Yo diría que no es una mala idea * cuando el nombre del módulo está en presencia de un espacio de nombres *, como un paquete. Este es el espíritu de PEP328. Ver mi respuesta a continuación. – OozeMeister

0

Sí, realmente no hay una buena manera de evitarlo. Intente no nombrar sus módulos como paquetes estándar. Si realmente desea llamar a su módulo time, le recomendaría usar _time.py en su lugar. Incluso si hubiera una manera de hacerlo, su código sería difícil de leer y confuso cuando se trata de los módulos de 2 tiempos.

4

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

Sin embargo, en Python 2.5+, creo que la reutilización de los nombres de módulo lib estándar dentro de un espacio de nombres de paquete está perfectamente bien; de hecho, eso es the spirit of PEP328.

A medida que la biblioteca de Python se expande, cada vez más módulos internos del paquete existentes aparecen de repente en los módulos de la biblioteca estándar por accidente. Es un problema particularmente difícil dentro de los paquetes porque no hay forma 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 el valor predeterminado porque son el caso de uso más común y porque las importaciones absolutas pueden proporcionar toda la funcionalidad de las importaciones relativas (dentro del paquete), aunque a costa de la dificultad renombrar las piezas del paquete más arriba en la jerarquía o al mover un paquete dentro de otro.

Debido a que este representa un cambio en la semántica, las importaciones absolutos serán opcionales en Python 2.5 y 2.6 a través del uso de from __future__ import absolute_import

SWS.time es claramente no lo mismo que time y como lector de la código, esperaría que SWS.time no solo utilizara time, sino que lo extienda de alguna manera.

lo tanto, si SWS.foo necesita importar SWS.time, entonces se debe utilizar 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, se debe utilizar un explícita relativa de las importaciones 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 estándar lib time dentro del módulo SWS.time, primero deberá importar la función futura (solo para Python) 2.5+; Python 3+ hace esto por defecto):

# inside of SWS.time 
from __future__ import absolute_import 

import time 

time.sleep(28800) # time for bed 

Nota:from __future__ import absolute_imports sólo afectará a las declaraciones de importación dentro del módulo que la función futura es importado y se no afectará a ningún otro módulo (ya que ello ser perjudicial si otro módulo depende de las importaciones relativas).

+0

Tenga en cuenta que su presupuesto de PEP 8 es ** obsoleto **. La versión actual de PEP 8 * respalda el uso de importaciones relativas *: cita: * las importaciones relativas explícitas son una alternativa aceptable a las importaciones absolutas, especialmente cuando se trata de diseños complejos de paquetes donde el uso de importaciones absolutas sería innecesariamente detallado * – Bakuriu

+1

@Bakuriu, bien maldito. No sabía que las PEP podrían cambiar así. Actualizaré mi respuesta. Sin embargo, mantendré mi argumento de que tener un módulo empaquetado cuyo nombre sea el mismo que el de un módulo stdlib de nivel superior no solo es permisible, sino que también lo es. – OozeMeister

Cuestiones relacionadas