2009-08-11 10 views
6

Consente di dire che sono in un file chiamato openid.py e faccio:Python: Come posso scegliere quale modulo importare quando sono lo stesso nome

from openid.consumer.discover import discover, DiscoveryFailure 

devo il modulo openid sul mio PYTHONPATH ma il interprete sembra stia cercando di usare il mio file openid.py. Come posso ottenere la versione della libreria?

(Naturalmente, qualcosa di diverso dall'ovvia risposta "rinomina il file" sarebbe bello).

+7

'rinominare il file' – SilentGhost

+0

Qual è il motivo per cui non rinominare il file? Sembra una piccola correzione rispetto a cercare un modo per aggirarla. – Zoomulator

+0

Il file dovrebbe essere semanticamente chiamato openid, poiché si trova in un modulo con "tipi" di alias. openid è il nome del tipo. –

risposta

9

Questo è il motivo per cui le importazioni assolute sono state scelte come nuovo comportamento predefinito. Tuttavia, non sono ancora predefiniti in 2.6 (forse in 2.7 ...). È possibile ottenere il loro comportamento ora importandoli dal futuro:

from __future__ import absolute_import 

Potete saperne di più su questo nel PEP metnioned da Nick o (più facile da capire, credo) nel documento "What's New in Python 2.5".

3

Rinominarlo. Questa è l'idea dietro gli spazi dei nomi. il tuo openid potrebbe essere un sottomodulo nel tuo modulo principale project. il tuo email si scontrerà con il modulo superiore email in stdlib.

perché il tuo openid non è universale, fornisce un caso speciale per il tuo progetto.

+4

In realtà, penso che l'idea che sta dietro agli spazi dei nomi sia * non * di doverla rinominare in qualcosa di unico;) myproject.openid è qualcosa di diverso da openid. Con le nuove importazioni assolute, l'importazione openid otterrà sempre il modulo a livello di sistema (ad esempio stdlib) e il relativo .openid otterrà il sottomodulo openid nel modulo corrente. – c089

+0

ovviamente non lo è. ** Se ** ha il suo modulo 'project' di quanto dovrebbe usare' project.openid'. Non è chiaro perché OP sta facendo quello che sta facendo, ma se non ha il modulo 'project', allora dovrebbe rinominare' openid' in qualcos'altro. – SilentGhost

+0

corretto. fuori dal pacchetto è pkg.openid. Ma all'interno del file "openid.py" non riesco ad accedere alla libreria "openid". Questo è il problema principale –

1

È possibile utilizzare le importazioni relative o assolute (in base alle specifiche della propria situazione), che sono trattate di recente nello PEP 328. Ovviamente, sul serio, non dovresti creare conflitti di denominazione come questo e dovresti rinominare il tuo file.

+0

Anche se il nome semanticamente corretto per il file è openid? Come se fosse in una directory di tipi di alias insieme a email, pagina web, dominio, ecc.? –

+0

@Paul: anche allora. Se si trova in una "directory di tipi di alias", allora dovrebbe essere un pacchetto, e quindi è pkg.openid, che non è ambiguo. –

+0

corretto. fuori dal pacchetto è pkg.openid. Ma all'interno del file "openid.py" non riesco ad accedere alla libreria "openid". Questo è il problema principale –

-1

Si potrebbe provare a mischiare sys.path, per spostare le directory interessanti in primo piano prima di eseguire l'importazione.

+0

Non sarà di aiuto se 'sys.modules ['openid']' è già impostato, come sarebbe nel caso dell'OP come in 'openid.py'. –

+0

@Alex Perché dovrebbe essere così? Il file corrente viene automaticamente aggiunto a sys.modules? Un quick test.py <"import sys; print sys.modules.keys()", quando eseguito, suggerisce il contrario !? – ThomasH

+0

Un modulo che è _importato_ viene aggiunto a sys.modules con il suo vero nome; l'unico file che viene eseguito come "programma principale" ottiene invece il nome convenzionale di "__main__". Ma se stai eseguendo quel file openid.py come modulo principale, in primo luogo non c'è motivo di averlo su sys.path! –

2

Non voglio entrare nella polemica sulla ridenominazione e preferisco invece mostrarti come fare ciò che vuoi (se è "buono per te" o no ;-). La soluzione non è difficile ...

Basta impostare __path__! Una piccola dimostrazione:

$ 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! 

questa mostra un modulo OpenID riuscendo a importare un pacchetto di omonima anche se il percorso del modulo viene fornito in precedenza in sys.path, esys.modules['openid'] è chiaramente già impostato in quel momento. E tutto il "segreto" è in semplice codice di openid.py ...:

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

senza l'assegnazione __path__, naturalmente, sarebbe solo emettere Module!.

Funziona anche per l'importazione di sottomoduli all'interno del pacchetto, ovviamente. Do:

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

e modificare openid.ultima linea di py per

from openid import submod 

e vedrete:

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

Riguardo a sys.modules ['openid'] impostato. L'hai detto anche in un altro commento, ma non ne sono così sicuro. Perché dovrebbe essere così? Il file corrente viene automaticamente aggiunto a sys.modules? Un quick test.py <"import sys; print 'test' in sys.modules.keys()", quando eseguito, suggerisce il contrario !? – ThomasH

+0

Come ho risposto all'altro commento: l'unico file che viene eseguito come il modulo principale va in 'sys.modules ['__ main __']' invece (dato che il suo '__name__' è impostato artificialmente e convenzionalmente su' __main__'). Ecco perché sto ** importando qui openid, per mostrare che '__path__' funziona ancora. Se tutto ciò di cui hai bisogno w/openid.py è eseguirlo come main allora non c'è motivo di averlo in sys.path. –

+0

Pensavo che il problema dell'OP derivi semplicemente dal fatto che "." arriva prima in sys.path, quindi la directory corrente viene ricercata per 'openid' dove viene trovato lo script openid.py di importazione. Ma se si spostano le directory 'interessanti' di sys.path in primo piano, l'altro 'openid' (il modulo) viene trovato per primo, e tutto va bene. – ThomasH

Problemi correlati