2011-01-11 14 views
22
stuff/ 
    __init__.py 
    mylib.py 
    Foo/ 
     __init__.py 
     main.py 
     foo/ 
      __init__.py 
      script.py 

script.py vuole importare mylib.pycome eseguire l'importazione relativa in pitone

Questo è solo un esempio, ma in realtà voglio solo fare un import parente di un modulo in una directory padre. Ho provato varie cose e ottengo questo errore ...

Attempted relative import beyond toplevel package

ho letto da qualche parte che lo script dal punto in cui il programma si avvia non dovrebbe nel pacchetto, e ho cercato di modificare la struttura per che in questo modo ...

stuff/ 
    mylib.py 
    foo.py // equivalent of main.py in above 
    foo/ 
     __init__.py 
     script.py 

ma ha ottenuto lo stesso errore.

Come posso realizzare questo? Questo è anche un approccio adeguato?

Edit: In Python 2

risposta

28

Dopo giocherellare con un po 'di più, mi sono reso conto come impostare l'alto, e per il bene di specificità non userò foo nomi di barre. La mia directory del progetto si configura come ...

tools/ 
    core/ 
     object_editor/ 
      # files that need to use ntlib.py 
      editor.py # see example at bottom 
      __init__.py 
     state_editor/ 
      # files that need to use ntlib.py 
      __init__.py 
     ntlib.py 
     __init__.py # core is the top level package 
    LICENSE 
    state_editor.py # equivalent to main.py for the state editor 
    object_editor.py # equivalent to main.py for the object editor 

Una linea in object_editor.py sembra ...

from core.object_editor import editor 

Una linea in editor.py sembra ...

from .. import ntlib 

o in alternativa

from core import ntlib 

La chiave è che nell'esempio che ho fornito nella domanda, lo script "principale" veniva eseguito dal pacchetto. Una volta spostato, creato un pacchetto specifico (core) e spostato la libreria che volevo condividere con gli editor (ntlib), tutto era hunky-dory.

+1

Hai capito. Quello che succede è che non è possibile utilizzare le importazioni relative dallo script che si sta eseguendo dalla riga di comando, in modo tale che dovrebbe essere al livello più alto dell'organizzazione, facendo riferimento alle cose sottostanti. –

+0

Perché lo script "principale" è stato eseguito dall'interno del pacchetto causa i problemi? – Bin

1

import ..foo..stuff.mylib dovrebbe essere ok

EDIT tolse l'estensione

+4

Non credo che questa è la sintassi valida. – random

+0

'da ..foo..stuff.mylib importa tutto 'dovrebbe essere ok – tekknolagi

+0

import sys sys.path.append() import Bar
tekknolagi

10

anche se il più a lungo "roba" non è nel PATH pitone hai altra scelta che aggiungere il percorso .

Se si conosce il livello della vostra script.py da cose che si può fare ad esempio:

import sys 
import os 
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) 
+9

Questo documento è documentato da qualche parte? Non che io non ti creda, ma nel caso volessi solo dire "ehi importa da 2 directory in su" è necessario modificare il percorso del sistema, devo vederlo con i miei occhi. – random

+0

Questo è quello che di solito faccio, anche se per dispetto. – jdm

+0

Non direi che è esattamente documentato in questo modo. anche se l'ho usato più volte. Modificherà semplicemente il percorso di sistema per il tuo script Python in esecuzione, non a livello globale nel sistema. Penso che non dovresti preoccuparti. : P –

1

Dal PEP sembra che non è possibile utilizzare una di importazione rispetto ad importare un file che non è confezionato.

Quindi si avrebbe bisogno di aggiungere un __init__.py di roba e cambiare le importazioni a qualcosa come from .mylib import *

Tuttavia, il PEP sembra fare alcuna indennità per mantenere mylib confezionato in un modulo. Quindi potrebbe essere necessario modificare il modo in cui si chiamano le funzioni della libreria.

Un'altra alternativa è quella di spostare mylib in un subpackage e importarlo come from .libpackage import mylib

7

Sto eseguendo Python 3.4.2 su Windows 7 e mi sono strappato i capelli.

Quando si esegue uno di questi:

python -m unittest python -m unittest scoprire

... ho l' 'importazione relativa Tentativo di là pacchetto toplevel' errore sarebbe.

Per me, la soluzione è stata l'eliminazione del ".." nel mio [test_stock.py]. La linea era: dall'importazione ..stock della

cambiato in: a magazzino di importazione della

.. e funziona.

struttura di cartelle:

C:\ 
    | 
    +-- stock_alerter 
      | 
      +-- __init__.py 
      +-- stock.py 
      | 
      \-- tests 
        | 
        +-- __init__.py 
        \-- test_stock.py 
+0

La tua soluzione funziona ma non riesco a capire perché ... Inoltre, Pycharm sta impazzendo con questo e evidenzia in rosso la dichiarazione –

+0

Funziona perché non è più un'importazione relativa quando rimuovi il '..'. Invece è un'importazione assoluta. PyCharm utilizzerà la directory sorgente del progetto per risolverlo, il che significa che potrebbe essere necessario aggiungere manualmente una directory nelle impostazioni del progetto per aiutarlo a risolvere le importazioni. – meowsqueak