python - Importazione di file da una cartella diversa


Ho la seguente struttura di cartelle.

application/app/folder/file.py

e voglio importare alcune funzioni da file.py in un altro file Python che risiede in

application/app2/some_folder/some_file.py

ho provato

from application.app.folder.file import func_name

e alcuni altri vari tentativi ma fino ad ora non sono riuscito a importare correttamente. Come posso fare questo?


Answers



Per impostazione predefinita, non è possibile. Quando si importa un file, Python cerca solo la directory corrente, la directory da cui viene eseguito lo script del punto di ingresso e sys.path che include posizioni come la directory di installazione del pacchetto (in realtà è un po 'più complessa di questa, ma copre la maggior parte dei casi).

Tuttavia, è possibile aggiungere al percorso Python in fase di runtime:

# some_file.py
import sys
sys.path.insert(0, '/path/to/application/app/folder')

import file



Non c'è niente di sbagliato in:

from application.app.folder.file import func_name

Assicurati che la cartella contenga anche un __init__.py , questo consente di includerlo come pacchetto. Non sono sicuro del perché le altre risposte parlino di PYTHONPATH.




Quando i moduli sono in posizioni parallele, come nella domanda:

application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py

Questa stenografia rende visibile un modulo all'altro:

import sys
sys.path.append('../')



Dal momento che la tua domanda sembra specifica * nix, penso che un modo pulito sarebbe utilizzare la variabile di ambiente

PYTHONPATH

come descritto nella documentazione: Python2 , Python3

export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH



Da quello che so, aggiungi un file __init__.py direttamente nella cartella delle funzioni che vuoi importare farà il lavoro.




Ha funzionato per me in python3 su linux

import sys  
sys.path.append(pathToFolderContainingScripts)  
from scriptName import functionName #scriptName without .py extension  



Considerando l' application come directory root per il tuo progetto python, crea un file __init__.py vuoto nelle cartelle application , app e folder . Quindi nel tuo some_file.py fai le modifiche come segue per ottenere la definizione di func_name:

import sys
sys.path.insert(0, r'/from/root/directory/application')

from application.app.folder.file import func_name ## You can also use '*' wildcard to import all the functions in file.py file.
func_name()



Questo funziona per me su Windows

# some_file.py on mainApp/app2 
import sys
sys.path.insert(0, sys.path[0]+'\\app2')

import some_file



Se lo scopo del caricamento di un modulo da un percorso specifico è di assistervi durante lo sviluppo di un modulo personalizzato, è possibile creare un collegamento simbolico nella stessa cartella dello script di test che punta alla radice del modulo personalizzato. Questo riferimento al modulo avrà la precedenza su qualsiasi altro modulo installato con lo stesso nome per qualsiasi script eseguito in quella cartella.

Ho provato questo su Linux, ma dovrebbe funzionare in qualsiasi sistema operativo moderno che supporta collegamenti simbolici.

Un vantaggio di questo approccio è che è possibile indicare un modulo che si trova nella propria copia di lavoro del ramo SVC locale, che può semplificare notevolmente il tempo di ciclo di sviluppo e ridurre le modalità di errore della gestione di diverse versioni del modulo.




Il tuo problema è che Python sta cercando nella directory Python questo file e non lo trova. Devi specificare che stai parlando della directory in cui ti trovi e non di quella Python.

Per fare questo si cambia questo:

from application.app.folder.file import func_name

a questa:

from .application.app.folder.file import func_name

Aggiungendo il punto che stai dicendo cerca in questa cartella la cartella dell'applicazione invece di cercare nella directory Python.

(Spero che questo risolva il tuo problema!)




Sono piuttosto speciale: utilizzo Python con Windows!

Completo semplicemente le informazioni: per Windows e Linux, sia il percorso relativo sia il percorso assoluto in sys.path (ho bisogno di percorsi relativi perché uso i miei script sui vari PC e sotto diverse directory principali).

E quando si usa Windows sia \ e / può essere usato come separatore per i nomi di file e, naturalmente, è necessario raddoppiare \ nelle stringhe Python,
alcuni esempi validi:

sys.path.append('c:\\tools\\mydir')
sys.path.append('..\\mytools')
sys.path.append('c:/tools/mydir')
sys.path.append('../mytools')

(nota: penso che / sia più conveniente di \ , event se è meno 'nativo di Windows' perché è compatibile con Linux e più semplice da scrivere e copiare su Windows explorer)




L'utilizzo di sys.path.append con un percorso assoluto non è l'ideale quando si sposta l'applicazione in altri ambienti. L'utilizzo di un percorso relativo non funzionerà sempre perché la directory di lavoro corrente dipende da come viene eseguito lo script.

Poiché la struttura della cartella dell'applicazione è fissa, possiamo utilizzare os.path per ottenere il percorso completo. Ad esempio, se questa è la struttura:

/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py

E diciamo che vuoi importare il modulo "mango". Potresti fare quanto segue in vanilla.py:

import sys, os.path
mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ '/another_folder/')
sys.path.append(mango_dir)
import mango

Certo, non hai bisogno della variabile mango_dir.

Per capire come funziona guarda questo esempio di sessione interattiva:

>>> import os
>>> mydir = '/home/me/application/app2/some_folder'
>>> newdir = os.path.abspath(os.path.join(mydir, '..'))
>>> newdir
    '/home/me/application/app2'
>>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder'
>>> 
>>> newdir
'/home/me/application/app2/another_folder'
>>> 

E controlla la documentazione di os.path .




Puoi aggiornare la shell di Python premendo f5, o vai a Run-> Esegui modulo. In questo modo non devi cambiare la directory per leggere qualcosa dal file. Python cambierà automaticamente la directory. Ma se vuoi lavorare con file diversi da diverse directory in Python Shell, puoi cambiare la directory in sys, come ha detto Cameron in precedenza.




sys.path.insert(0, '/path/to/application/app/folder')