2009-08-11 6 views
6

digamos que estoy en un archivo llamado openid.py y lo hago:Python: ¿Cómo puedo elegir qué módulo para importar cuando se nombran el mismo

from openid.consumer.discover import discover, DiscoveryFailure 

que tienen el módulo openid en mi PYTHONPATH pero el el intérprete parece estar intentando usar mi archivo openid.py. ¿Cómo puedo obtener la versión de la biblioteca?

(Por supuesto, algo bueno aparte de la respuesta obvia de "renombrar su archivo" sería bueno).

+7

'cambiar el nombre de su archivo' – SilentGhost

+0

¿Cuál es la razón para no cambiar el nombre del archivo? Parece una solución pequeña en comparación con estar buscando una forma de evitarlo. – Zoomulator

+0

El archivo debe llamarse semánticamente openid, ya que está en un módulo con "tipos" de alias. openid es el nombre del tipo. –

Respuesta

9

Esa es la razón por la que se han elegido las importaciones absolutas como el nuevo comportamiento predeterminado. Sin embargo, aún no son los predeterminados en 2.6 (tal vez en 2.7 ...). Usted puede obtener su comportamiento ahora importándolos desde el futuro:

from __future__ import absolute_import 

Usted puede encontrar más información sobre esto en el PEP metnioned por Nick o (más fácil de entender, creo) en el documento "What's New in Python 2.5".

3

Cambie el nombre. Esta es la idea detrás de los espacios de nombre. su openid podría ser un submódulo en su módulo superior project. su email chocará con el módulo superior email en stdlib.

porque su apertura no es universal, proporciona un caso especial para su proyecto.

+4

En realidad, creo que la idea detrás de los espacios de nombres es * no * tener que cambiarle el nombre a algo único;) myproject.openid es algo diferente de openid. Con las nuevas importaciones absolutas, importar openid siempre obtendrá el módulo de todo el sistema (por ejemplo, stdlib) y el relativo .openid obtendrá el submódulo openid en el módulo actual. – c089

+0

por supuesto que no lo es. ** Si ** él es su 'proyecto' de módulo de lo que debería estar usando 'project.openid'. No está claro por qué OP está haciendo lo que está haciendo, pero si no tiene el módulo 'project', entonces debe renombrar' openid' a otra cosa. – SilentGhost

+0

correcto. fuera del paquete es pkg.openid. Pero dentro del archivo "openid.py" no puedo acceder a la biblioteca "openid". Ese es el problema principal. –

1

Puede usar importaciones relativas o absolutas (dependiendo de los detalles de su situación), que se cubren en PEP 328 más recientemente. Por supuesto, en serio, no debería crear conflictos de nombres como este y debería cambiar el nombre de su archivo.

+0

¿Incluso si el nombre semánticamente correcto para el archivo es openid? ¿Te gusta si está en un directorio de tipos de alias junto con, correo electrónico, página web, dominio, etc.? –

+0

@Paul: incluso entonces. Si está en un "directorio de tipos de alias", entonces realmente debería ser un paquete, y luego es pkg.openid, que no es ambiguo. –

+0

correcto. fuera del paquete es pkg.openid. Pero dentro del archivo "openid.py" no puedo acceder a la biblioteca "openid". Ese es el problema principal. –

-1

Puede intentar mezclar sys.path, para mover los directorios interesantes al frente antes de importar.

+0

No ayuda si 'sys.modules ['openid']' ya está configurado, como sería en el caso del OP ya que está en 'openid.py'. –

+0

@Alex ¿Por qué sería ese el caso? ¿El archivo actual se agrega automáticamente a sys.modules? Un test.py <"import sys; print sys.modules.keys()" rápido, cuando se ejecuta, ¿sugiere lo contrario? – ThomasH

+0

Un módulo que es _importado_ se agrega a sys.modules bajo su nombre real; el único archivo que se ejecuta como el "programa principal" obtiene el nombre convencional de '__main__' en su lugar. ¡Pero si está ejecutando ese openid.py como el módulo principal, entonces no hay ninguna razón para tenerlo en sys.path en primer lugar! –

2

No entraré en la polémica sobre el cambio de nombre y en su lugar me centraré en mostrarte cómo hacer lo que quieres (si es "bueno para ti" o no ;-). La solución no es difícil ...

¡Acaba de configurar __path__! Una pequeña demostración:

$ mkdir /tmp/modules /tmp/packages 
$ mkdir /tmp/packages/openid 
$ echo 'print "Package!"' > /tmp/packages/openid/__init__.py 
$ gvim /tmp/modules/openid.py 
$ PYTHONPATH='/tmp/modules:/tmp/packages' python -c'import openid' 
Module! 
Package! 

esto muestra un módulo de openid gestión para importar un paquete del mismo nombre a pesar de que el camino del módulo viene antes en sys.path, ysys.modules['openid'] está claramente ya se consigna en ese momento. Y todo el "secreto" está en código simple de openid.py ...:

print "Module!" 
__path__ = ['/tmp/packages'] 
import openid 

sin la asignación __path__, por supuesto, sería solamente emiten Module!.

También funciona para la importación de submódulos dentro del paquete, por supuesto. Do:

$ echo 'print "Submod!"' > /tmp/packages/openid/submod.py 

y cambie openid.La última línea de py a

from openid import submod 

y verá:

$ PYTHONPATH='/tmp/modules:/tmp/packages' python -c'import openid' 
Module! 
Package! 
Submod! 
$ 
+0

Con respecto a los sys.modules ['openid'] que se están configurando. También dijiste esto en otro comentario, pero no estoy tan seguro. ¿Por qué sería ese el caso? ¿El archivo actual se agrega automáticamente a sys.modules? Un test.py <"import sys; print 'test' rápido en sys.modules.keys()", cuando se ejecuta, ¿sugiere lo contrario? – ThomasH

+0

Como respondí al otro comentario: el único archivo que se ejecuta como el módulo principal va en 'sys.modules ['__ main __']' en su lugar (ya que su '__name__' se establece artificial y convencionalmente en' __main__'). Es por eso que estoy ** importando ** openid aquí, para mostrar que '__path__' todavía funciona. Si todo lo que necesita w/openid.py es ejecutarlo como main, entonces no hay razón para tenerlo en sys.path. –

+0

Pensé que el problema del PO se deriva simplemente del hecho de que '.' viene antes en sys.path, por lo que el directorio actual se busca 'openid' donde se encuentra el script de importación openid.py. Pero si cambia los directorios 'interesantes' de sys.path a su frente, el otro 'openid' (el módulo) se encuentra primero, y todo está bien. – ThomasH

Cuestiones relacionadas