Come realizzare importazione relativa in pitone
-
09-10-2019 - |
Domanda
stuff/
__init__.py
mylib.py
Foo/
__init__.py
main.py
foo/
__init__.py
script.py
script.py
vuole importare mylib.py
Questa è solo un esempio, ma in realtà voglio solo fare un'importazione 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 dovrebbero nel pacchetto, e ho cercato di modificare la struttura per quello 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 fare questo? E 'questo anche un approccio adeguato?
Edit: In Python 2
Soluzione
Dopo giocherellare con un po 'di più, ho capito come impostare l'alto, e per amore di specificità non userò i nomi foo bar. 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 negli sguardi object_editor.py
come ...
from core.object_editor import editor
Una linea negli sguardi editor.py
come ...
from .. import ntlib
oppure
from core import ntlib
La chiave è che nell'esempio ho dato in questione, lo script "principale" è stato eseguito da all'interno del pacchetto. Una volta mi sono trasferito fuori, ha creato un pacchetto specifico (core
), e si è trasferito la biblioteca ho voluto i redattori alla quota (ntlib
) in quel pacchetto, tutto era rose e fiori.
Altri suggerimenti
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__), '..', '..'))
Io corro Python 3.4.2 su Windows 7 e strappò i capelli fuori su questo.
Quando si esegue uno di questi:
python -m unittest python -m unittest scoprire
... Vorrei ottenere il 'importazione relativa Tentativo di là pacchetto toplevel' errore.
Per me, la soluzione era caduta la ".." 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
import ..foo..stuff.mylib
dovrebbe essere ok
EDIT tolse l'estensione
PEP appare 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 in qualcosa di simile from .mylib import *
Tuttavia, il PEP sembra fare alcuna indennità per mylib mastio confezionato in un modulo. Così potrebbe essere necessario per cambiare il modo di chiamare le funzioni di libreria.
Un'altra alternativa è quella di spostare mylib in un subpackage e importarlo come from .libpackage import mylib
Se siete su Linux o forse un simile * nix, è possibile incidere questo con collegamenti simbolici.
stuff/
mylib.py
foo.py // equivalent of main.py in above
foo/
script.py
mylib.py -> ../mylib.py
foo2/
script2.py
mylib.py -> ../mylib.py
Questo non è probabilmente un buon modello da seguire.
Nel mio caso ho optato per questo perché ho avuto più eseguibili dipendenti dalla stessa libreria che aveva bisogno di essere messo in directory separate.
Realizzazione di nuovi test eseguibili non dovrebbero richiedere lo scrittore prova di avere una profonda comprensione delle importazioni pitone.
tests/
common/
commonlib.py
test1/
executable1.py
executable2.py
commonlib.py -> ../common/commonlib.py
test2/
executable1.py
executable2.py
commonlib.py -> ../common/commonlib.py