2009-08-11 12 views
274

Ho un file chiamato tester.py, situato su /project.Importare un file da una sottodirectory?

/project ha una sottodirectory chiamata lib, con un file chiamato BoxTime.py:

/project/tester.py 
/project/lib/BoxTime.py 

voglio importare BoxTime da tester. Ho provato questo:

import lib.BoxTime 

che ha portato:

Traceback (most recent call last): 
    File "./tester.py", line 3, in <module> 
    import lib.BoxTime 
ImportError: No module named lib.BoxTime 

Delle idee come importare BoxTime dalla sottodirectory?

EDIT

La __init__.py era il problema, ma non dimenticate di fare riferimento a BoxTime come lib.BoxTime, o l'uso:

import lib.BoxTime as BT 
... 
BT.bt_function() 

risposta

353

Date un'occhiata alla documentazione di pacchetti (paragrafo 6.4) qui: http://docs.python.org/tutorial/modules.html

In breve, è necessario inserire un file vuoto denominato

__init__.py 

nella directory "lib".

+28

Perché ci si sente * * hacky? È il modo in cui Python segna le directory di importazione sicure/disponibili. – IAbstract

+5

Non solo contrassegna le directory di importazione sicure/disponibili, ma fornisce anche un modo per eseguire un codice di inizializzazione durante l'importazione di un nome di directory. – Sadjad

+12

Sì, questo è hacky e anche sporco, e secondo me il linguaggio non dovrebbe imporre il suo modo di caricare i file attraverso il filesystem. In PHP abbiamo risolto il problema lasciando che il codice userland registrasse più funzioni di autoloading chiamate quando manca uno spazio dei nomi/classe. Quindi la comunità ha prodotto lo standard PSR-4 e il compositore lo implementa, e al giorno d'oggi nessuno si deve preoccupare di ciò. E niente stupidi file '__init__' con hardcoded (ma se lo vuoi, registra semplicemente un hook di caricamento automatico! Questa è la differenza tra _hacky_ e _hackable_). –

11

Prova import .lib.BoxTime. Per maggiori informazioni leggere l'importazione relativa in PEP 328.

+2

Non penso di aver mai visto quella sintassi usata prima. C'è una forte ragione (non) per usare questo metodo? – tgray

+1

Perché non era questa la risposta. Certo, se vuoi fare l'intera cosa dei pacchetti, dovresti farlo. Ma non è quello che era la domanda originale. –

+0

Questo mi dà: ValoreErrore: Tentativo importazione relativa in non-pacchetto – Alex

19

La directory lib contiene un file __init__.py?

Python utilizza __init__.py per determinare se una directory è un modulo.

108
  • Creare una sottodirectory denominata lib.
  • Creare un file vuoto denominato lib\__init__.py.
  • In lib\BoxTime.py, scrivere una funzione foo() come questo:

    def foo(): 
        print "foo!" 
    
  • Nel codice cliente nella directory sopra lib, scrivere:

    from lib import BoxTime 
    BoxTime.foo() 
    
  • eseguire il codice cliente.Otterrete:

    foo! 
    

Molto più tardi - in linux, sarebbe simile a questa:

% cd ~/tmp 
% mkdir lib 
% touch lib/__init__.py 
% cat > lib/BoxTime.py << EOF 
heredoc> def foo(): 
heredoc>  print "foo!" 
heredoc> EOF 
% tree lib 
lib 
├── BoxTime.py 
└── __init__.py 

0 directories, 2 files 
% python 
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from lib import BoxTime 
>>> BoxTime.foo() 
foo! 
+0

Potresti fornire un link alla documentazione di Python dove questo è spiegato? Grazie! – Zenon

+1

@Zenon, prova questo: docs.python.org/tutorial/modules.html#packages – hughdbrown

32

si può provare inserendola in sys.path:

sys.path.insert(0, './lib') 
import BoxTime 
+6

Questo è ottimo se per qualche motivo non puoi o non vuoi creare il file __init__.py. – jpihl

+1

non sembra funzionare per me (errore 'Nessun modulo ..') – minsk

+1

Funziona se si esegue python dalla directory "progetto". Il "." è interpretato in relazione alla tua attuale directory di lavoro, non relativa alla directory in cui il file che stai eseguendo. Diciamo 'cd/data',' python ../ project/tester.py'. Quindi non funzionerà. – morningstar

0

prova questo:

from lib import BoxTime

+1

senza alcuna spiegazione questo non è molto utile. –

6

mi fare questo, che copre praticamente tutti i casi (assicuratevi di avere __init__.py in relativa/path/to/la vostra lib/cartella /):

import sys, os 
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/relative/path/to/your/lib/folder") 
import someFileNameWhichIsInTheFolder 
... 
somefile.foo() 


Esempio:
Hai nella cartella del tuo progetto:

/root/myproject/app.py 

avete in un'altra cartella del progetto:

/root/anotherproject/utils.py 
/root/anotherproject/__init__.py 

si desidera utilizzare /root/anotherproject/utils.py e chiamare la funzione foo, che è in esso.

Così si scrive in app.py:

import sys, os 
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../anotherproject") 
import utils 

utils.foo() 
+1

se stai usando 'os.path' probabilmente vuoi usare' os.path.join ((os.path.dirname (os.path.realpath (__ file __)), '..', 'anotherproject') ' invece di codificare il "/" nella concatenazione del percorso. – cowbert

0

Creare un file vuoto __init__.py nella sottodirectory/lib. E aggiungere al inizio del codice principale

from __future__ import absolute_import 

poi

import lib.BoxTime as BT 
... 
BT.bt_function() 

o meglio

from lib.BoxTime import bt_function 
... 
bt_function() 
Problemi correlati