Domanda

Immaginate di questa struttura di directory:

app/
   __init__.py
   sub1/
      __init__.py
      mod1.py
   sub2/
      __init__.py
      mod2.py

Io sono di codifica mod1, e ho bisogno di importare qualcosa da mod2.Come devo fare?

Ho provato from ..sub2 import mod2 ma sto diventando un "Tentato relativa importazione in non-package".

Ho googlato in giro ma ho trovato solo "sys.path manipolazione hack.Non c'è un modo pulito?


Edit:tutti i miei __init__.py's sono attualmente vuoto

Edit2:Sto cercando di fare questo, perché sub2 contiene le classi che sono condivisi attraverso i pacchetti sub (sub1, subX, etc.).

Edit3:Il comportamento che sto cercando è la stessa descritta nel PEP 366 (grazie John B)

È stato utile?

Soluzione

Sembra che tutti voglio raccontare che cosa si dovrebbe fare, piuttosto che rispondere alla domanda.

Il problema è che si sta eseguendo il modulo come '__main__', passando il mod1.py come argomento per l'interprete.

Da PEP 328:

Relativa importazioni uso di un modulo __nome__ attributo per determinare il modulo della posizione nella gerarchia del pacchetto.Se il modulo del nome non contengano informazioni sul pacchetto (ad es.è impostato a '__main__') quindi relativa importazioni sono risolti come se il modulo fosse un alto livello di modulo, indipendentemente dal luogo in cui il modulo è in realtà che si trova nel file system.

In Python 2.6, stanno aggiungendo la capacità di moduli di riferimento relativa al modulo principale. PEP 366 descrive il cambiamento.

Aggiornamento:Secondo Nick Coghlan, l'alternativa consigliata è quello di eseguire il modulo all'interno di un pacchetto utilizzando l'opzione-m.

Altri suggerimenti

main.py
setup.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       module_a.py
    package_b/ ->
       __init__.py
       module_b.py
  1. Si esegue python main.py.
  2. main.py fa: import app.package_a.module_a
  3. module_a.py non import app.package_b.module_b

In alternativa 2 o 3 potrebbe utilizzare: from app.package_a import module_a

Che funzionerà fino a quando si dispone di app nel PYTHONPATH. main.py potrebbe essere ovunque quindi.

Così la scrittura di un setup.py per copiare (installare) l'intero pacchetto di app e sotto-sistema di destinazione python cartelle, e main.py al sistema di destinazione le cartelle di script.

Ecco la soluzione che funziona per me:

Faccio la relativa importazioni from ..sub2 import mod2 e poi, se voglio correre mod1.py poi vado alla directory padre di app e eseguire il modulo utilizzando python -m-switch python -m app.sub1.mod1.

Il vero motivo per cui questo problema si verifica con relativa importazioni, è quello relativo importazioni lavora prendendo il __name__ proprietà del modulo.Se il modulo viene gestito direttamente, quindi __name__ è impostato per __main__ e non contengono alcuna informazione circa la struttura del pacchetto.E, ecco perché python si lamenta per il relative import in non-package errore.

Così, utilizzando l'opzione-m-fornire la struttura del pacchetto di informazioni per python, attraverso il quale è possibile risolvere il relativo importazioni con successo.

Ho riscontrato questo problema molte volte mentre si fa relativa importazioni.E, dopo aver letto tutte le risposte precedenti, non ero ancora in grado di capire come risolverlo, in modo pulito, senza bisogno di mettere il codice standard in tutti i file.(Anche se alcuni commenti sono stati molto utili, grazie a @ncoghlan e @XiongChiamiov)

Spero che questo aiuta qualcuno che è in lotta con relativa importazioni problema, perché passare attraverso il PEP è davvero divertente.

"Guido vista l'esecuzione di script all'interno di un pacchetto come un anti-pattern" (respinto PEP-3122)

Ho trascorso così tanto tempo a cercare di trovare una soluzione, la lettura di post qui su Stack Overflow e dicendo a me stesso: "ci deve essere un modo migliore!".Sembra che ci sia non.

Questo è risolto al 100%:

  • app/
    • main.py
  • impostazioni/
    • local_setings.py

Importazione settings/local_setting.py in app/main.py:

main.py:

import sys
sys.path.insert(0, "../settings")


try:
    from local_settings import *
except ImportError:
    print('No Import')
def import_path(fullpath):
    """ 
    Import a file with full path specification. Allows one to
    import from anywhere, something __import__ does not do. 
    """
    path, filename = os.path.split(fullpath)
    filename, ext = os.path.splitext(filename)
    sys.path.append(path)
    module = __import__(filename)
    reload(module) # Might be out of date
    del sys.path[-1]
    return module

Sto usando questo frammento di codice per importare i moduli da sentieri, speranza che aiuta

spiegazione di nosklo's risposta con esempi

nota:tutti __init__.py i file sono vuoti.

main.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       fun_a.py
    package_b/ ->
       __init__.py
       fun_b.py

app/package_a/fun_a.py

def print_a():
    print 'This is a function in dir package_a'

app/package_b/fun_b.py

from app.package_a.fun_a import print_a
def print_b():
    print 'This is a function in dir package_b'
    print 'going to call a function in dir package_a'
    print '-'*30
    print_a()

main.py

from app.package_b import fun_b
fun_b.print_b()

se si esegue $ python main.py restituisce:

This is a function in dir package_b
going to call a function in dir package_a
------------------------------
This is a function in dir package_a
  • main.py fa: from app.package_b import fun_b
  • fun_b.py non from app.package_a.fun_a import print_a

così il file nella cartella package_b utilizzato file nella cartella package_a, che è ciò che si desidera.Giusto??

Questo è, purtroppo, un sys.percorso di trucco, ma funziona abbastanza bene.

Ho incontrato questo problema con un altro strato:Ho già avuto un modulo avente il nome specificato, ma era il modulo sbagliato.

quello che volevo fare era la seguente (il modulo stavo lavorando era modulo3):

mymodule\
   __init__.py
   mymodule1\
      __init__.py
      mymodule1_1
   mymodule2\
      __init__.py
      mymodule2_1


import mymodule.mymodule1.mymodule1_1  

Nota che ho già installato miomodulo, ma nella mia installazione non ho "mymodule1"

e vorrei avere un ImportError perché stava cercando di importare dal mio moduli installati.

Ho provato a fare un sys.percorso.aggiungere, e che non ha funzionato.Che cosa ha fatto il lavoro è un sys.percorso.inserire

if __name__ == '__main__':
    sys.path.insert(0, '../..')

Così una specie di hack, ma ha tutto quello che serve per lavorare!Quindi, tenere a mente, se si desidera che la vostra decisione di ignorare gli altri percorsi allora avete bisogno di usare sys.percorso.insert(0, pathname) per farlo funzionare!Questo è stato molto frustrante punto di attaccare per me, assegnare delle persone dicono di usare il "append" funzione sys.il percorso, ma questo non funziona se si dispone già di un modulo definito (mi trovo molto strano comportamento)

Mi permetta solo di mettere questo qui per il mio riferimento.So che non è bene che il codice Python, ma ho bisogno di uno script per un progetto su cui stavo lavorando e ho voluto mettere lo script in un scripts directory.

import os.path
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

Come @EvgeniSergeev dice nei commenti per l'OP, è possibile importare il codice da un .py file in una posizione arbitraria con:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()

Questa è presa dal questo MODO di rispondere.

Da Python doc,

In Python 2.5, è possibile passare importare il comportamento di assoluta importazioni utilizzando un from __future__ import absolute_import direttiva.Questo assoluto di importazione di comportamento predefinito in una versione futura (probabilmente Python 2.7).Una volta assoluto delle importazioni di default, import string sempre la standard di versione della libreria.Si è suggerito che gli utenti dovrebbero iniziare a utilizzare assoluto importazioni per quanto possibile, quindi è preferibile iniziare a scrivere from pkg import string nel tuo codice

L'ho trovato più facile per impostare "PYTHONPATH" variabile d'ambiente per la cartella di livello superiore:

bash$ export PYTHONPATH=/PATH/TO/APP

quindi:

import sub1.func1
#...more import

naturalmente, PYTHONPATH è "globale", ma non sollevare problemi per me ancora.

In cima a quello che Giovanni B ha detto, sembra che l'impostazione del __package__ variabile dovrebbe aiutare, invece di cambiare __main__ che potrebbe rovinare le altre cose.Ma, per quanto ho potuto testare, è completamente non funziona come dovrebbe.

Ho lo stesso problema e né PEP 328 366 risolvere completamente il problema, come sia, alla fine della giornata, hanno bisogno della testa del pacchetto, per essere inclusi nel sys.path, per quanto ho potuto capire.

Vorrei anche ricordare che non ho trovato la procedura per formattare la stringa che dovrebbe andare in quelle variabili.È "package_head.subfolder.module_name" cosa????

Si supponga di eseguire al livello superiore, quindi in mod1 uso:

import sub2.mod2 

invece di

from ..sub2 import mod2
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top