Importa il pacchetto python dalla directory locale nell'interprete


87

Sto sviluppando / testando un pacchetto nella mia directory locale. Voglio importarlo nell'interprete (v2.5), ma sys.path non include la directory corrente. In questo momento digito sys.path.insert(0,'.'). Esiste un modo migliore?

Anche,

from . import mypackage

fallisce con questo errore:

ValueError: Attempted relative import in non-package

Dove l'hai letto "." era un modulo Python?
S.Lott,

16
@Lott: È un percorso di importazione relativo descritto qui: docs.python.org/reference/…
projectshave

1
Potresti voler guardare questa guida definitiva chrisyeh96.github.io/2017/08/08/…
Kevin Zhu

Risposte:


46

Puoi usare le importazioni relative solo da un modulo che è stato a sua volta importato come parte di un pacchetto - il tuo script o interprete interattivo non lo era, quindi ovviamente from . import(che significa "importare dallo stesso pacchetto da cui sono stato importato") non funziona. import mypackagesarà bene una volta a garantire la directory padre di mypackageè in sys.path(come sei riuscito a ottenere la vostra directory corrente via da sys.pathIo non so -? hai qualcosa di strano in site.py, o ...)

In sys.patheffetti, per riportare la directory corrente non c'è modo migliore che metterla lì.


Python 2.5 per Ubuntu 8.10 non ha la directory corrente (stringa vuota) in sys.path per l'interprete. Non ho cambiato nulla, quindi in qualche modo è stato spedito in quel modo. Ho appena installato 3.0 e sys.path HA "" in sys.path.
projectshave

@projectshave, OK, Ubuntu ha senza dubbio le sue ragioni! Non l'ho notato nella 8.04 (quello che usiamo attualmente al lavoro) ma forse non stavo prestando abbastanza attenzione.
Alex Martelli

1
Mi sbaglio parzialmente. Python invocato da una shell ha la directory corrente in sys.path. Python invocato da Emacs non ha la directory corrente. Strano.
projectshave

1
Ah beh, allora è Emacs ad avere le loro ragioni rispetto a quelle di Ubuntu (come utente vim non lo so veramente ;-). Puoi inserire condizionatamente "." nel tuo sys.path se non c'è ovviamente.
Alex Martelli

@Alex Martelli: grazie mille! Ho cercato e cercato la soluzione al motivo per cui il mio componente aggiuntivo (per Anki) necessitava di un'istruzione di importazione diversa quando veniva eseguito "localmente" come script. Quando invece ho aggiunto un metodo local_launch () e ho importato / lanciato il tutto da uno script esterno alla cartella del pacchetto, ha funzionato a meraviglia!
Jon Coombs

18

Consulta la documentazione per sys.path:

http://docs.python.org/library/sys.html#sys.path

Per citare:

Se la directory dello script non è disponibile (ad es. Se l'interprete viene invocato in modo interattivo o se lo script viene letto dallo standard input), path [0] è la stringa vuota, che indirizza Python a cercare prima i moduli nella directory corrente.

Quindi, non è necessario eseguire la scimmia con sys.path se si avvia l'interprete Python dalla directory contenente il modulo.

Inoltre, per importare il tuo pacchetto, fai semplicemente:

import mypackage

Poiché la directory contenente il pacchetto è già in sys.path, dovrebbe funzionare bene.


1
Fallirà se un nome file simile esiste da qualche altra parte nell'ambiente di lavoro.
JAR.JAR.beans

@ JAR sys.path.
SpoonMeiser

3
Buon punto. Cioè, se eseguiamo il file dalla directory locale. Nel caso sia un'altra cartella, e nel caso sia necessaria una modifica a sys.path, significa sys.path.insert(0, new_path)invece di sys.path.append(new_path).
JAR.JAR.beans

15

Se vuoi eseguire uno script Python non modificato in modo che importi le librerie da una directory locale specifica, puoi impostare la PYTHONPATHvariabile d'ambiente, ad esempio in bash:

export PYTHONPATH=/home/user/my_libs
python myscript.py

Se vuoi solo importare dalla directory di lavoro corrente usa la .notazione:

export PYTHONPATH=.
python myscript.py

L'esportazione di PYTHONPATH include la programmazione al di fuori di python (ad esempio in bash). Inoltre, in docs.python.org/3/using/cmdline.html è chiaramente indicato che " il percorso di ricerca predefinito dipende dall'installazione ".
ilias iliadis

13

Mantienilo semplice:

 try:
     from . import mymodule     # "myapp" case
 except:
     import mymodule            # "__main__" case

7
Mi piace questa soluzione, è la più semplice. L'unica domanda che rimane è perché la regola "solo un modo per farlo" è stata ritenuta facoltativa durante l'implementazione delle importazioni ... Seriamente, ci sono circa 15 modi per dichiarare e organizzare i pacchetti, tutti con inconvenienti
Léo Germond

5

Un modo semplice per farlo funzionare è eseguire lo script dalla directory genitore utilizzando il -mflag di python , ad es python -m packagename.scriptname. Ovviamente in questa situazione hai bisogno di un __init__.pyfile per trasformare la tua directory in un pacchetto.


5

All'interno di un pacchetto se c'è setup.py , allora meglio installarlo

pip install -e .

3

L'utilizzo sys.pathdovrebbe includere già la directory corrente.

Provare:

import .

o:

from . import sth

tuttavia potrebbe non essere una buona pratica, quindi perché non usare semplicemente:

import mypackage

5
Il problema con <import mypackage> è che caricherà il pacchetto dall'env python globale, potrebbe caricare il pacchetto / file dalla cartella locale, ma potrebbe anche caricare qualche altro mypackge casuale che si trova nell'ambiente di lavoro.
JAR.JAR.beans

3

Un po 'tardi per la festa, ma questo è quello che ha funzionato per me:

>>> import sys
>>> sys.path.insert(0, '')

Apparentemente, se c'è una stringa vuota, Python sa che dovrebbe cercare nella directory corrente. Non avevo la stringa vuota sys.path, che ha causato questo errore.


1

Ero solito pathlibaggiungere la mia directory del modulo al mio percorso di sistema perché volevo evitare di installare il modulo come pacchetto e la risposta di @maninthecomputer non funzionava per me

import sys
from pathlib import Path

cwd = str(Path(__file__).parent)
sys.path.insert(0, cwd)
from my_module import my_function
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.