Frage

Stellen Sie sich diese Verzeichnisstruktur:

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

Ich bin Codierung mod1, und ich brauche etwas von mod2 zu importieren. Wie soll ich es tun?

Ich habe versucht, from ..sub2 import mod2 aber ich bin immer einen "Versuchte relativ Import in nicht-Paket".

gegoogelt ich um, fand aber nur "sys.path Manipulation" Hacks. Gibt es nicht eine saubere Art und Weise?


Edit: Alle meine __init__.py des derzeit leer sind

Edit2: Ich versuche, dies zu tun, weil sub2 enthält Klassen, die über Teilpakete geteilt werden (sub1, subX usw.)

.

Edit3: Das Verhalten ich suche ist das gleiche wie in PEP 366 (dank John B)

War es hilfreich?

Lösung

Jeder scheint sagen zu wollen, was Sie sollen nicht nur die Frage zu beantworten tun.

Das Problem ist, dass Sie das Modul als ‚__main__‘ laufen durch die mod1.py als Argument an den Interpreter übergeben.

PEP 328 :

  

Relative Importen verwenden, um ein Attribut des __name__ Modul, das Modul in der Position der Pakethierarchie zu bestimmen. Wenn der Name keine Paketinformationen enthält das Modul (zB es wird auf ‚__main__‘) dann relativ Importe aufgelöst werden, als ob das Modul ein Top-Level-Modul waren, unabhängig davon, wo das Modul tatsächlich auf dem Dateisystem entfernt.

In Python 2.6, sie um die Möglichkeit Module in Bezug auf das Hauptmodul zu verweisen. PEP 366 beschreibt die Änderung.

Aktualisieren :. Laut Nick Coghlan, die empfohlene Alternative ist das Modul innerhalb des Pakets mit der Option -m ausführen

Andere Tipps

main.py
setup.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       module_a.py
    package_b/ ->
       __init__.py
       module_b.py
  1. Sie führen python main.py.
  2. main.py tut: import app.package_a.module_a
  3. module_a.py hat import app.package_b.module_b

Alternativ 2 oder 3 verwenden könnte: from app.package_a import module_a

Das funktioniert so lange, wie Sie in Ihrem PYTHONPATH app haben. main.py könnte überall dann sein.

So schreiben Sie einen setup.py kopieren (Installation) die gesamte App-Paket und Subpackages auf die Python-Ordner des Zielsystems und main.py Systems Skript Ordner abzuzielen.

Hier ist die Lösung, die für mich funktioniert:

ich die relativen Importe als from ..sub2 import mod2 und dann, wenn ich mod1.py laufen wollen, dann gehe ich in das übergeordnete Verzeichnis von app und führen Sie das Modul der Python Option -m als python -m app.sub1.mod1 verwendet wird.

Der wahre Grund, warum dieses Problem mit einer relativen Importe auftritt, ist, dass eine relative Importe funktioniert, indem die __name__ Eigenschaft des Moduls nehmen. Wenn das Modul direkt ausgeführt wird, dann wird __name__ auf __main__ und es enthält keine Informationen über Paketstruktur. Und das ist, warum Python über die relative import in non-package Fehler beschwert.

Also, indem Sie den Schalter -m mit Ihnen die Paketstruktur Informationen zu Python, durch die sie die relativen Einfuhren erfolgreich lösen können.

Ich habe dieses Problem oft anzutreffen, während eine relative Importe zu tun. Und nachdem alle bisherigen Antworten gelesen hatte, war ich noch nicht in der Lage, herauszufinden, wie es zu lösen, in eine saubere Art und Weise, ohne in allen Dateien vorformulierten Code setzen zu müssen. (Obwohl einige der Kommentare sehr hilfreich waren, dank @ncoghlan und @XiongChiamiov)

Hoffe, das hilft jemand, der mit relativ Importe Problem kämpft, weil durch PEP geht wirklich nicht lustig ist.

„Guido Ansichten Skripte in einem Paket als Anti-Muster läuft“ (abgelehnt PEP-3122 )

Ich habe so viel Zeit damit verbracht, eine Lösung zu finden, relevante Beiträge hier auf Stack-Überlauf zu lesen und sagte mir: „Es muss einen besseren Weg geben!“. Sieht aus wie ist es nicht.

Dies ist gelöst 100%:

  • app /
    • main.py
  • Einstellungen /
    • local_setings.py

Einstellungen importieren / 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

Ich verwende diese Schnipsel-Module von Pfaden, die Hoffnung zu importieren, die

helfen

Erklärung von nosklo's Antwort mit Beispielen

Hinweis: Alle __init__.py Dateien sind leer

.
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()

Wenn Sie $ python main.py führen Sie es zurück:

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 tut: from app.package_b import fun_b
  • fun_b.py hat from app.package_a.fun_a import print_a

so in Ordnern package_b Datei Datei im Ordner package_a verwendet, das ist das, was Sie wollen. Recht ??

Dies ist leider ein sys.path Hack, aber es funktioniert ganz gut.

Ich habe dieses Problem mit einer anderen Schicht. Ich hatte bereits ein Modul mit dem angegebenen Namen, aber es war das falsche Modul

, was ich war folgende (das Modul arbeitete ich von war module3) tun wollte:

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


import mymodule.mymodule1.mymodule1_1  

Beachten Sie, dass ich bereits mymodule installiert haben, aber in meiner Installation habe ich nicht „mymodule1“

, und ich würde einen Import bekommen, weil es aus meinen installierten Module zu importieren versucht.

Ich habe versucht, eine sys.path.append zu tun, und das hat nicht funktioniert. Was hat funktioniert ein war sys.path.insert

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

So Art ein Hack, aber hat alles zu arbeiten! Also denken Sie daran, wenn Sie Ihre Entscheidung möchten außer Kraft setzen andere Pfade , dann müssen Sie sys.path.insert nutzen (0, Pfadname), um es an die Arbeit! Dies war eine sehr frustrierende Knackpunkt für mich, zuzuteilen Leute sagen, die „anhängen“ -Funktion sys.path zu verwenden, aber das funktioniert nicht, wenn Sie bereits ein Modul definiert haben (ich finde es sehr seltsames Verhalten)

Lassen Sie mich nur hier für meine eigene Referenz setzen. Ich weiß, dass es nicht gut Python-Code ist, aber ich brauchte einen Skript für ein Projekt, das ich arbeite, und ich wollte das Skript in einem scripts Verzeichnis setzen.

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

Wie @EvgeniSergeev in den Kommentaren zum OP sagt, können Sie Code aus einer .py Datei an einem beliebigen Ort importieren mit:

import imp

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

Dies wird von diese SO beantworten .

Hier finden Sie aktuelle http: // docs.python.org/whatsnew/2.5.html#pep-328-absolute-and-relative-imports . Sie tun können,

from .mod1 import stuff

Python doc ,

  

In Python 2.5 können Sie importieren das Verhalten absolute Importe schalten eine from __future__ import absolute_import Direktive. Dieses Absolut- Importverhalten wird der Standard in einer zukünftigen Version (wahrscheinlich Python 2.7) wird. Sobald absolute Importe der Standard sind, werden import string immer die Standard-Bibliothek Version. Es wird vorgeschlagen, dass die Nutzer sollten mit absoluten Importen so viel wie möglich beginnen, so ist es vorzuziehen, from pkg import string in Ihrem Code zu beginnen Schreiben

Ich fand es einfacher „PYTHONPATH“ Umgebungsvariable auf den obersten Ordner festlegen:

bash$ export PYTHONPATH=/PATH/TO/APP

dann:

import sub1.func1
#...more import

natürlich PYTHONPATH ist „global“, aber es hat nicht Probleme aufwerfen für mich noch.

Am Anfang was John B sagte, scheint es, wie die __package__ variable Einstellung sollte, statt zu ändern __main__ helfen, die anderen Dinge vermasseln könnte. Aber soweit ich konnte testen, ist es nicht vollständig funktioniert, wie es sollte.

Ich habe das gleiche Problem und weder PEP 328 oder 366 lösen das Problem vollständig, da beide bis zum Ende des Tages, müssen Sie den Kopf des Pakets in sys.path aufgenommen werden, soweit ich verstehen konnte.

Ich sollte auch erwähnen, dass ich nicht finden, wie die Zeichenfolge zu formatieren, die in diese Variablen gehen sollte. Ist es "package_head.subfolder.module_name" oder was?

Angenommen, Sie auf der obersten Ebene laufen, dann in mod1 Verwendung:

import sub2.mod2 

statt

from ..sub2 import mod2
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top