2015-09-24 17 views
6

Qual è il modo corretto in Python per importare un modulo da una directory di livello superiore? La directory è un pacchetto Python con tutti questi moduli e ho una sottodirectory con codice che richiede questi moduli.Importare un modulo da una directory (pacchetto) di livello superiore

Il seguente funziona bene, ma questo è solo un trucco. Mi piacerebbe un modo consigliato/pitonioso.

import sys 
sys.path.append("../") 
from fruit import Fruit 
print("OK") 

La struttura di directory:

pkg1 
    __init__.py 
    fruit.py 
    +sub_pkg 
     __init__.py 
     recipe.py 

contenuto di fruit.py

class Fruit: 
    def get_name(self): 
     print("Fruit name") 

contenuto di sub_pkg/recipe.py .. solo una singola linea di importazione:

from fruit import Fruit 

Quando ho correre :

python recipe.py 

dà il seguente errore.

Traceback (most recent call last): 
    File "recipe.py", line 2, in <module> 
    from fruit import Fruit 
ImportError: No module named fruit 

Ho anche provato: from pkg1.fruit import Fruit, non funziona. Anche guardato altre domande simili .. python -m recipe.py o python -m sub_pkg/recipe.py non ha funzionato.

+0

Cosa per questa risposta: http://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python –

+0

Cosa è l'errore che stai ricevendo per 'da pkg1.fruit import Fruit'? – Forge

+0

@Irit: 'ImportError: nessun modulo denominato temp.fruit' – stackjs

risposta

2

Nel file principale recipe.py aggiungere pkg1 percorso del PYTHONPATH

sys.path.append('/path/to/pkg1') 

o utilizzare un percorso relativo

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

Ciò dovrebbe consentire l'importazione di pkg1 da ogni dove nel vostro programma.

C'è sempre la possibilità di utilizzare le importazioni relative come suggerito qui, trovo utilizzando le importazioni assoluti più leggibile e meno probabilità di portare a bug. Inoltre, nei progetti di grandi dimensioni che utilizzano le importazioni relative, dovrai calcolare costantemente le gerarchie dei percorsi mentre quando si utilizzano le importazioni assolute, è semplice sapere che si fa sempre riferimento a una directory principale.

Chi importazioni relativi da PEP328 in Python 2.5:

Reading code which relies on relative imports is also less clear, because a reader may be confused about which module is intended to be used. Python users soon learned not to duplicate the names of standard library modules in the names of their packages’ submodules, but you can’t protect against having your submodule’s name being used for a new module added in a future version of Python.


Guido sta suggerendo utilizzando punti principali delle importazioni relative ad evitare importazioni ambigue come sopra descritto, da PEP328 ancora:

Guido has Pronounced that relative imports will use leading dots. A single leading dot indicates a relative import, starting with the current package. Two or more leading dots give a relative import to the parent(s) of the current package, one level per dot after the first.

+0

impostazione PYTHONPATH ha funzionato e sembra una soluzione accettabile (aggiungendo il pkg al percorso di ricerca) in base alla documentazione. Avevo già provato sys.path.append, ma ho deciso di non andare in quel modo – stackjs

2

In caso di problemi è possibile utilizzare anche quanto segue.

Questo importazioni dalla directory corrente

from . import something 

questa importazione da una directory sopra

from .. import fruit 

Doc per il percorso relativo: https://docs.python.org/2/tutorial/modules.html#intra-package-references

RELATIVA PACCHETTO DI EMISSIONE ValueError: Tentativo relativa importazione a non -package

Per le persone che hanno problemi con il pacchetto relativo. Ecco la tua soluzione.

if __name__ == "__main__" and __package__ is None: 
    __package__ = "expected.package.name" 

Anche la spiegazione, copiato da un altro python docs

When the main module is specified by its filename, then the package attribute will be set to None . To allow relative imports when the module is executed directly, boilerplate similar to the following would be needed before the first relative import statement:

if __name__ == "__main__" and __package__ is None: 
    __package__ = "expected.package.name 

Note that this boilerplate is sufficient only if the top level package is already accessible via sys.path . Additional code that manipulates sys.path would be needed in order for direct execution to work without the top level package already being importable.

Doc per la creazione di pacchetti io non ho intenzione di incollare il contenuto dal momento che è piuttosto lungo, ma ecco la sezione sui documenti python per la creazione di pacchetti. https://docs.python.org/2/tutorial/modules.html#packages

One altri documenti sul PYTHONPATH https://docs.python.org/2/using/cmdline.html#envvar-PYTHONPATH

+0

Quasi allo stesso tempo !! – avenet

+0

grazie .. se faccio uno di questi, risulta in 'ValoreError: Tentativo importazione relativa in non-pacchetto'. Questo è lo stesso errore mostrato da Olexander in un'altra domanda. Ma non ho capito la soluzione! – stackjs

+0

Si fa riferimento al documento. Questo è sempre più vantaggioso. – AdriVelaz

-1

Invece di usare le importazioni superiori, avere un punto di ingresso che è possibile chiamare dal livello più alto e le tue importazioni sono relative a quel punto di ingresso nel tuo file recipe.py.

Es:

pkg1/ 
    __init__.py 
    main.py 
    fruit.py 
    +sub_pkg 
     __init__.py 
     recipe.py 

Dove main.py contiene:

#!/usr/bin/env python3 

import subpkg.recipe as recipe 
import fruit 

if __package__ is None and __name__ == "__main__": 
    __package__ = "main" 
    print() 
    # Call recipe.py or fruit.py methods from here 

E in recipe.py:

import fruit 
# do stuff with fruit module, which is properly imported now 

a correre, chiamare python3 main.py

+0

Sarebbe più vantaggioso indirizzare semplicemente il pacchetto all'interno dello script. invece di creare uno script di esecuzione separato. Ciò rimuove la possibilità di uno script in esecuzione su di esso, che potrebbe non essere scalabile in alcuni scenari. – AdriVelaz

+0

Indirizzo @AdriVelaz quale pacchetto in quale elenco? Ho bisogno di un po 'di contesto – NuclearPeon

+0

'__PACKAGE__ = "expected.package.name"' ' Utilizzando if __name__ == "__main __":' sul livello di script Ecco la documentazione così. https://www.python.org/dev/peps/pep-0366/#proposed-change – AdriVelaz

Problemi correlati