2010-11-03 13 views
10

Non mi è stato chiaro come denominare correttamente questa domanda.Precedenza all'importazione di Python: pacchetti o moduli?

Caso 1

Si supponga che ho la seguente struttura di directory.

foo 
| 
+- bar/__init__.py 
| 
+- bar.py 

Se ho

from foo import bar 

Come faccio a sapere quale bar (bar.py o bar/__init__.py) viene importato? C'è un modo semplice per rilevare automaticamente questo si verifica?

Caso 2

foo 
| 
+- foo.py 
| 
+- other.py 

Se other.py ha la linea

import foo 

Come faccio a sapere che foo (foo o foo.foo) viene importato? Ancora una volta, c'è un modo semplice per rilevare automaticamente ciò che si verifica?

+2

Un modo semplice per rilevarlo: hanno prima linea di bar.py essere 'di stampa (" bar .py importato ")' – nmichaels

+2

Dovrei avere RTFM-ed. http://docs.python.org/tutorial/modules.html è una grande risorsa. –

+0

Esiste un modo per forzare il programma a utilizzare un'interpretazione o l'altra? – Sobi

risposta

6

TLDR; un pacchetto ha la precedenza su un modulo con lo stesso nome se si trovano nella stessa directory.

Dalla documentazione:

"Quando un modulo di nome spam viene importato, l'interprete cerca un file chiamato spam.py nella directory corrente, e quindi nella lista di directory specificata dalla variabile di ambiente PYTHONPATH. Questo ha la stessa sintassi della variabile di shell PATH, cioè un elenco di nomi di directory. "

Questo è un po 'fuorviante, perché l'interprete sarà anche cercare un pacchetto chiamato spam (una directory chiamata spam che contiene un file __init__.py). Poiché le voci della directory vengono ordinate prima della ricerca, i pacchetti hanno la precedenza sui moduli con lo stesso nome se si trovano nella stessa directory perché spam arriva prima dello spam.py.

Si noti che "directory corrente" è relativa al percorso di script principale (quello in cui __name__ == '__main__' is True). Quindi se si è a /home/billg chiamando /foo/bar.py, "directory corrente" si riferisce a /foo.

+1

Le cose sono cambiate? perché non sembra che la directory corrente venga aggiunta come suggerisci tu. I documenti ora dichiarano: "Quando viene importato un modulo chiamato spam, l'interprete cerca dapprima un modulo predefinito con quel nome: se non viene trovato, cerca un file chiamato spam.py in un elenco di directory dato dal variabile sys.path. " E non vedo che la "directory corrente" sia elencata. Ma dato che mi sono perso forse sto fraintendendo? – PatrickT

+1

E (potrei essere frainteso tutto questo) una precedente risposta StackOverflow afferma, "Python non aggiunge la directory corrente a sys.path, ma piuttosto la directory in cui è inserito lo script." http://stackoverflow.com/questions/2325923/how-to-fix-importerror-no-module-named-error-in-python – PatrickT

+0

Questa risposta non sembra ** Caso 1 ** – qff

0

nel primo caso si sta cercando di importare la barra delle funzioni da file 'foo.py'

Nel secondo si sta cercando di importare il file 'foo.py'

2

Pacchetti (directory con __init__.py) hanno la precedenza sui moduli. La documentazione di questo fatto è difficile da trovare ma è possibile vederla nella fonte: python 2.7, python 3.6 (grazie a @qff per la ricerca).

Avrete anche bisogno di un __init__.py all'interno della directory foo per il vostro esempio di lavoro.

Se other.py è dentro di foo/ allora caricherà foo.py (non la directory foo/) perché cercherà nella directory corrente prima (a meno che non hai giocato con PYTHONPATH o sys.path).

+0

Come fai a sapere che ha la precedenza? - Non riuscivo a trovarlo in [la documentazione di Python] (https://docs.python.org/2/tutorial/modules.html) – qff

+0

@qff l'ho provato. Ho anche testato python3 proprio ora e ha lo stesso comportamento. Un link alla documentazione ufficiale del fatto sarebbe buono. Se ne trovi uno, non esitate a modificare la mia risposta o postare un commento e io lo modificherò. – kanaka

+0

Trovato! (tipo di) - le voci di una directory vengono ordinate prima di provare a caricarle come pacchetto o modulo. Questo assicura che i pacchetti vengano caricati per primi. [Collegamento al codice sorgente CPython] (https://github.com/python/cpython/blob/c30098c8c6014f3340a369a31df9c74bdbacc269/Lib/pkgutil.py#L235) – qff

5

da una shell Python:

from foo import bar 

print bar.__file__ 

dovrebbe dirvi quale file è stato importato

Rob

+0

non ha attributo __file__ su python3 – gabn88

Problemi correlati