Importieren Sie ein Modul aus einem relativen Pfad

759

Wie importiere ich ein Python-Modul anhand seines relativen Pfads?

Wenn beispielsweise dirFooenthält Foo.pyund dirBar, und dirBarenthält Bar.py, wie importiere ich Bar.pyin Foo.py?

Hier ist eine visuelle Darstellung:

dirFoo\
    Foo.py
    dirBar\
        Bar.py

Foomöchte einbeziehen Bar, aber eine Umstrukturierung der Ordnerhierarchie ist keine Option.

Jude Allred
quelle
2
Sieht aus wie stackoverflow.com/questions/72852/… , vielleicht?
Joril
3
Überprüfen Sie meine Antwort, sie ist die vollständigste, andere funktionieren in besonderen Fällen nicht, beispielsweise wenn Sie das Skript aus einem anderen Verzeichnis oder aus einem anderen Python-Skript aufrufen. Siehe stackoverflow.com/questions/279237/…
sorin
Ich hatte ein ähnliches Problem und fand es und es funktioniert !! apt-get install Python-Profiler
ldcl289
5
Nur für den Fall, dass jemand es statisch machen möchte und hierher kommt (wie ich :)), können Sie auch die Umgebungsvariable
PYTHONPATH
Besser ist es, die Anweisungen in Lib / site.py für jeden Fall zu befolgen
Avenida Gez

Antworten:

333

Angenommen, Ihre beiden Verzeichnisse sind echte Python-Pakete (enthalten die __init__.pyDatei), ist hier eine sichere Lösung für die Aufnahme von Modulen relativ zum Speicherort des Skripts.

Ich gehe davon aus, dass Sie dies tun möchten, da Sie Ihrem Skript eine Reihe von Modulen hinzufügen müssen. Ich verwende dies in der Produktion in mehreren Produkten und arbeite in vielen speziellen Szenarien wie: Skripten, die aus einem anderen Verzeichnis aufgerufen oder mit Python Execute ausgeführt werden, anstatt einen neuen Interpreter zu öffnen.

 import os, sys, inspect
 # realpath() will make your script run, even if you symlink it :)
 cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
 if cmd_folder not in sys.path:
     sys.path.insert(0, cmd_folder)

 # Use this if you want to include modules from a subfolder
 cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"subfolder")))
 if cmd_subfolder not in sys.path:
     sys.path.insert(0, cmd_subfolder)

 # Info:
 # cmd_folder = os.path.dirname(os.path.abspath(__file__)) # DO NOT USE __file__ !!!
 # __file__ fails if the script is called in different ways on Windows.
 # __file__ fails if someone does os.chdir() before.
 # sys.argv[0] also fails, because it doesn't not always contains the path.

Als Bonus können Sie mit diesem Ansatz Python zwingen, Ihr Modul anstelle der auf dem System installierten zu verwenden.

Warnung! Ich weiß nicht wirklich, was passiert, wenn sich das aktuelle Modul in einer eggDatei befindet. Es scheitert wahrscheinlich auch.

Sorin
quelle
5
Kann ich eine Erklärung bekommen, wie das funktioniert? Ich habe ein ähnliches Problem und ich würde LIEBEN, ein Python-Modul DIR zu erzwingen, anstatt eine Suche durchzuführen
carl crott
Unter Win 7 Pro 64x und Python 2.7 werden einige Fehler angezeigt. 1) Ich musste inspect zur Importliste hinzufügen. 2) Der erste Wert [0] im Tupel ist eine leere Zeichenfolge. Die zweite [1] zeigt den Dateinamen. Ich vermute, dass der erste der Weg sein sollte ... Irgendwelche Ideen?
Adam Lewis
2
Wenn Sie einen Unterordner werden, verwenden Sie es wie folgt aus : os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]) + "/subfolder")Do NOT den Unterordner hinzufügen , bevor abspathda dies schwerwiegende Fehler verursacht.
Maximilian Hils
4
@ scr4ve Sie sollten stattdessen os.path.join () verwenden, und Sie können den Fall ( cmd_subfolder) gerne direkt zu meiner Antwort hinzufügen . Vielen Dank!
Sorin
7
für mich entstehen realpathschon absolute pfade, die ich also nicht brauche abspath. Auch os.path.dirnamekann anstelle von Split verwendet werden, makeing die Indizierung [0]obsolet. Die Linie wäre dann:os.path.realpath(os.path.dirname(inspect.getfile(inspect.currentframe())))
Uhr
328

Stellen Sie sicher, dass dirBar die __init__.pyDatei hat - dies macht ein Verzeichnis zu einem Python-Paket.

S.Lott
quelle
204
Beachten Sie, dass diese Datei vollständig leer sein kann.
Harley Holcombe
47
Wenn sich das übergeordnete Verzeichnis von dirBar nicht befindet, hilft sys.pathdas Vorhandensein von __init__.pyim dirBarVerzeichnis nicht viel.
JFS
7
-1, das Hinzufügen __init.py__funktioniert nur, wenn sich das Verzeichnis bereits in sys.path befindet und in meinem Fall nicht. Die Lösung von "sorin" (akzeptiert) funktioniert immer.
Czarek Tomczak
12
"Wenn sich das Verzeichnis bereits in sys.path befindet". Wie können wir erraten, dass das Verzeichnis nicht in sys.pathder Frage enthalten ist? Vielleicht wurde etwas ausgelassen, von dem wir nichts gesehen oder gewusst haben?
S.Lott
4
Dies ist mit NEIN die Antwort auf die Frage: Ob die Initialisierungsdatei vorhanden ist oder nicht, lässt Python nicht in die Unterverzeichnisse schauen. Wie kam es zu Hunderten von Upvotes?
Gented
261

Sie können das Unterverzeichnis auch Ihrem Python-Pfad hinzufügen, damit es als normales Skript importiert wird.

import sys
sys.path.insert(0, <path to dirFoo>)
import Bar
Andrew Cox
quelle
6
Es sieht aus , dass Ihre Antwort nicht funktioniert mit relativen Pfaden finden stackoverflow.com/questions/279237/...
bogdan
24
Dies funktioniert mit relativen Pfaden - Sie müssen nur verstehen, dass ein relativer Pfad davon abhängt, aus welchem ​​Verzeichnis Sie ausgeführt werden. Dies macht dies zu einer schlechten Lösung für alles andere als einen schnellen Hack.
Nobar
12
Sie können so etwas wiesys.path.append(os.path.dirname(__file__) + "/relative/path/to/module")
Falko
odersys.path.append(__name__ if __name__ != '__main__' else __loader__.fullname)
vim
1
Erwägen Sie die Verwendung, sys.path.insert(0, <path to dirFoo>)da dieses Modul vor den an anderer Stelle gespeicherten gleichnamigen Modulen geladen wird.
Anton Tarasenko
117
import os
import sys
lib_path = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'lib'))
sys.path.append(lib_path)

import mymodule
Lefakir
quelle
2
Ich mag das, weil Sie die Flexibilität haben, ein Verzeichnis aufzurufen.
Charles L.
21
Sie sollten os.path.join()anstelle von '/' verwenden, wodurch die (lahmen) Fenster unterbrochen werden.
0xc0de
18
Das ist nicht zuverlässig. Dies hängt vom aktuellen Arbeitsverzeichnis ab und nicht von dem Verzeichnis, in dem sich das Skript befindet.
Jamesdlin
Möglicherweise möchten Sie nur hinzufügen, wenn der Pfad nicht bereits im Pfad enthalten ist. lib_path = os.path.abspath ('../ functions') wenn lib_path nicht in sys.path: sys.path.append (lib_path)
Brent
als Antwort auf @jamesdlin einige Antworten kombinieren: Was ist mit os.path.abspath(os.path.join(__file__,'..','lib'))?
Matthew Davis
107

Führen Sie einfach einfache Schritte aus, um die .py-Datei aus einem anderen Ordner zu importieren.

Angenommen, Sie haben ein Verzeichnis wie:

lib/abc.py

Bewahren Sie dann einfach eine leere Datei wie angegeben im lib-Ordner auf

__init__.py

Und dann benutzen

from lib.abc import <Your Module name>

Bewahren Sie die __init__.pyDatei in jedem Ordner der Hierarchie des Importmoduls auf.

Deepak 'Kaseriya'
quelle
79

Wenn Sie Ihr Projekt folgendermaßen strukturieren:

src\
  __init__.py
  main.py
  dirFoo\
    __init__.py
    Foo.py
  dirBar\
    __init__.py
    Bar.py

Dann sollten Sie von Foo.py aus in der Lage sein:

import dirFoo.Foo

Oder:

from dirFoo.Foo import FooObject

Laut Toms Kommentar muss der srcOrdner entweder über site_packagesoder über Ihren Suchpfad zugänglich sein . Außerdem wird, wie er erwähnt, __init__.pyimplizit importiert, wenn Sie zum ersten Mal ein Modul in dieses Paket / Verzeichnis importieren. In der Regel __init__.pyist einfach eine leere Datei.

Bouvard
quelle
Erwähnen Sie auch, dass init .py importiert wird, wenn das erste Modul in diesem Paket importiert wird. Außerdem funktioniert Ihr Beispiel nur, wenn sich src in den site_packages (oder im Suchpfad) befindet
Tom Leys
3
Dies ist die einfachste Lösung, nach der ich gesucht habe. Wenn sich die zu importierende Datei sicher in einem der Unterverzeichnisse befindet, ist diese Lösung ein Juwel.
Deepak GM
Ich habe das Gleiche versucht und bin gescheitert. Keine Ahnung warum. ImportError: Kein Modul namens customMath
Ming Li
9
Warum sollte jemand Foo aus Foo.py selbst importieren wollen? Sollte von Bar.py sein, denke ich.
Bhaskarc
from dirFoo import Foozu sagen Foo.bla(). Bei Verwendung import dirFoo.Foosollte man verwenden dirFoo.Foo.bla()- ziemlich hässlich auch ohne Kamelkoffer.
Cees Timmerman
45

Die einfachste Methode ist die Verwendung von sys.path.append ().

Möglicherweise interessieren Sie sich aber auch für das imp- Modul. Es bietet Zugriff auf interne Importfunktionen.

# mod_name is the filename without the .py/.pyc extention
py_mod = imp.load_source(mod_name,filename_path) # Loads .py file
py_mod = imp.load_compiled(mod_name,filename_path) # Loads .pyc file 

Dies kann verwendet werden, um Module dynamisch zu laden, wenn Sie den Namen eines Moduls nicht kennen.

Ich habe dies in der Vergangenheit verwendet, um eine Plugin-Schnittstelle für eine Anwendung zu erstellen, in der der Benutzer ein Skript mit anwendungsspezifischen Funktionen schreibt und das Skript einfach in einem bestimmten Verzeichnis ablegt.

Diese Funktionen können auch nützlich sein:

imp.find_module(name[, path])
imp.load_module(name, file, pathname, description)
Mönch
quelle
Beachten Sie, dass in der Dokumentation imp.load_source und imp.load_compiled als veraltet aufgeführt sind. Stattdessen werden imp.find_module und imp.load_module empfohlen.
Amicitas
@amicitas, können Sie bitte eine Referenz dafür angeben (ich brauche sie und verwende Python 2.6. Ich weiß, was 2.7-Dokumente dazu sagen, konnte aber keine Referenz zu 2.6 finden)
0xc0de
@ 0xc0de Sie finden diese Anweisung in den Dokumenten für das imp-Modul für Python 2.7.3 und Python 2.6.7 . Es sieht so aus, als ob diese Funktionen nicht einmal in den Dokumenten für Python 3.2 enthalten sind.
Amicitas
44

Dies ist der relevante PEP:

http://www.python.org/dev/peps/pep-0328/

Angenommen, dirFoo ist ein Verzeichnis von dirBar ...

In dirFoo \ Foo.py:

from ..dirBar import Bar
Peter Crabtree
quelle
Es hat für mich funktioniert, nur init .py für jeden Ordner hinzugefügt und Erfolg zu importieren
Yussan
23

Der einfachste Weg, ohne Änderungen an Ihrem Skript vorzunehmen, besteht darin, die Umgebungsvariable PYTHONPATH festzulegen. Weil sys.path von folgenden Speicherorten aus initialisiert wird:

  1. Das Verzeichnis, das das Eingabeskript enthält (oder das aktuelle Verzeichnis).
  2. PYTHONPATH (eine Liste von Verzeichnisnamen mit derselben Syntax wie die Shell-Variable PATH).
  3. Die installationsabhängige Standardeinstellung.

Renn einfach:

export PYTHONPATH=/absolute/path/to/your/module

Ihr sys.path enthält den obigen Pfad, wie unten gezeigt:

print sys.path

['', '/absolute/path/to/your/module', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PIL', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client', '/usr/lib/python2.7/dist-packages/ubuntuone-client', '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel', '/usr/lib/python2.7/dist-packages/ubuntuone-couch', '/usr/lib/python2.7/dist-packages/ubuntuone-installer', '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']
James Gan
quelle
13

Meiner Meinung nach ist es die beste Wahl, __ init __.py in den Ordner zu legen und die Datei mit aufzurufen

from dirBar.Bar import *

Es wird nicht empfohlen, sys.path.append () zu verwenden, da möglicherweise ein Fehler auftritt, wenn Sie denselben Dateinamen wie das vorhandene Python-Paket verwenden. Ich habe das nicht getestet, aber das wird nicht eindeutig sein.

jhana
quelle
komisch das from dirBar.Bar import *funktioniert aber nicht from dirBar.Bar import Bar. Weißt du warum * funktioniert? Was wäre, wenn ich mehrere Dateien in dirBar / hätte und nur einige davon abrufen wollte (mit einer Methode wie der, die Sie hier gepostet haben)?
Tester
2
@tester: Verwenden from dirBar import Bar.
Nobar
@tester, weil das fromdie Quelle angibt und alles, was danach importkommt, was von dieser Quelle zu holen ist. from dirBar.Bar import Barbedeutet "Aus der Quelle die Quelle selbst importieren", was keinen Sinn ergibt. das *obwohl bedeutet, "gib mir alles von der Quelle"
FuriousFolder
11

Der schnelle und schmutzige Weg für Linux-Benutzer

Wenn Sie nur herumspielen und sich nicht um Bereitstellungsprobleme kümmern, können Sie einen symbolischen Link verwenden (vorausgesetzt, Ihr Dateisystem unterstützt dies), um das Modul oder Paket direkt im Ordner des anfordernden Moduls sichtbar zu machen.

ln -s (path)/module_name.py

oder

ln -s (path)/package_name

Hinweis: Ein "Modul" ist eine beliebige Datei mit der Erweiterung .py und ein "Paket" ist ein beliebiger Ordner, der die Datei enthält __init__.py(dies kann eine leere Datei sein). Unter dem Gesichtspunkt der Verwendung sind Module und Pakete identisch - beide legen ihre enthaltenen "Definitionen und Anweisungen" offen, wie über den importBefehl angefordert .

Siehe: http://docs.python.org/2/tutorial/modules.html

kein Balken
quelle
10
from .dirBar import Bar

anstatt:

from dirBar import Bar

Nur für den Fall, dass eine andere dirBar installiert sein könnte und einen foo.py-Reader verwirren könnte.

jgomo3
quelle
2
Ich konnte dies unter Windows nicht tun. Ist das unter Linux?
Gabriel
1
Es funktioniert mit einem Skript, das Foo importiert. dh: main.py importiert dirFoo.Foo. Wenn Sie versuchen, Foo.py als Skript auszuführen, schlägt dies fehl. Siehe stackoverflow.com/questions/72852/…
jgomo3
9

Um in diesem Fall Bar.py in Foo.py zu importieren, würde ich diese Ordner zunächst wie folgt in Python-Pakete umwandeln:

dirFoo\
    __init__.py
    Foo.py
    dirBar\
        __init__.py
        Bar.py

Dann würde ich es so in Foo.py machen:

from .dirBar import Bar

Wenn ich wollte, dass der Namespace wie Bar aussieht. was auch immer oder

from . import dirBar

Wenn ich den Namespace dirBar.Bar haben wollte. was auch immer . Dieser zweite Fall ist nützlich, wenn Sie mehr Module unter dem dirBar-Paket haben.

Al Conrad
quelle
7

Fügen Sie eine __init__.py- Datei hinzu:

dirFoo\
    Foo.py
    dirBar\
        __init__.py
        Bar.py

Fügen Sie dann diesen Code zum Start von Foo.py hinzu:

import sys
sys.path.append('dirBar')
import Bar
Josh
quelle
5
Wenn dirBares sich bereits um ein Python-Paket handelt (aufgrund der Existenz von dirBar/__init__.py), müssen Sie es nicht anhängen dirBar, sys.pathoder? Die Aussage import Barvon Foo.pysollte ausreichen.
Santa
5

Beispiel für einen relativen sys.path:

# /lib/my_module.py
# /src/test.py


if __name__ == '__main__' and __package__ is None:
    sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../lib')))
import my_module

Basierend auf dieser Antwort.

Der_Meister
quelle
5

Wie Sie bereits erwähnt haben, möchten Sie normalerweise Zugriff auf einen Ordner mit Ihren Modulen haben, der sich darauf bezieht, wo Ihr Hauptskript ausgeführt wird. Sie importieren sie also einfach.

Lösung:

Ich habe das Skript D:/Books/MyBooks.pyund einige Module (wie oldies.py). Ich muss aus dem Unterverzeichnis importieren D:/Books/includes:

import sys,site
site.addsitedir(sys.path[0] + '\\includes')
print (sys.path)  # Just verify it is there
import oldies

Platzieren Sie ein print('done')in oldies.py, damit Sie überprüfen, ob alles in Ordnung ist. Diese Methode funktioniert immer, da nach der Python-Definition, sys.pathdie beim Programmstart initialisiert wurde, das erste Element dieser Listepath[0] das Verzeichnis ist, das das Skript enthält, mit dem der Python-Interpreter aufgerufen wurde.

Wenn das Skriptverzeichnis nicht verfügbar ist (z. B. wenn der Interpreter interaktiv aufgerufen wird oder wenn das Skript aus der Standardeingabe gelesen wird), path[0]ist dies die leere Zeichenfolge, die Python anweist, zuerst die Module im aktuellen Verzeichnis zu suchen. Beachten Sie, dass das Skriptverzeichnis vor den Einträgen eingefügt wird, die als Ergebnis von eingefügt wurden PYTHONPATH.

Avenida Gez
quelle
1
site.addsitedir(sys.path[0]+'/includes')In meinem ersten einfachen Python-Programm break_time.py musste ich einen Schrägstrich anstelle von zwei umgekehrten Schrägstrichen (dh ) verwenden: https://github.com/ltfschoen/PythonTest . Ich benutze System: MacOS 10.11.5, Python 2.7.12, IDLE IDE 2.7.12, Tk 8.5.9
Luke Schoen
4

Einfach können Sie verwenden: from Desktop.filename import something

Beispiel:

vorausgesetzt, die Datei ist Name test.pyim Verzeichnis Users/user/Desktopund wird alles importieren.

der Code:

from Desktop.test import *

Stellen Sie jedoch sicher, dass Sie __init__.pyin diesem Verzeichnis eine leere Datei mit dem Namen " " erstellen

0x1996
quelle
1
Von Importen mit Sternen wird abgeraten. siehe: stackoverflow.com/questions/2386714/why-is-import-bad
Axolotl
Ich weiß, deshalb habe ich zuerst geschrieben, import somethingdann sagte ich, es einfacher zu machen, es ist * nicht gut für RAM und auch wenn 2 Funktionen den gleichen Namen haben, wird es Ihren Code zusammenfassen
0x1996
3

Eine andere Lösung wäre, das py-require- Paket zu installieren und dann das Folgende in zu verwendenFoo.py

import require
Bar = require('./dirBar/Bar')
Niklas R.
quelle
Die URL scheint tatsächlich pypi.org/project/require.py zu sein , und beachten Sie, dass sie über Pip installiert werden muss.
Flash Sheridan
1
@FlashSheridan Nein, das ist ein anderes Projekt. Ich habe py-require gelöscht, da ich sicher war, dass niemand es verwendet, aber ich habe nicht an diesen Beitrag gedacht. Wenn Sie noch eine require()Funktion benötigen , können Sie sich mein Node.py-Projekt ansehen: github.com/nodepy/nodepy
Niklas R
2

Hier ist eine Möglichkeit, eine Datei von einer Ebene über dem relativen Pfad zu importieren.

Verschieben Sie das Arbeitsverzeichnis einfach um eine Ebene (oder einen beliebigen relativen Speicherort) nach oben, fügen Sie es Ihrem Pfad hinzu und verschieben Sie das Arbeitsverzeichnis wieder dorthin, wo es begonnen hat.

#to import from one level above:
cwd = os.getcwd()
os.chdir("..")
below_path =  os.getcwd()
sys.path.append(below_path)
os.chdir(cwd)
Justin Müller
quelle
1
Ich verstehe deine Logik hier nicht. es ist zu kompliziert
transilvlad
0

Ich habe keine Erfahrung mit Python. Wenn meine Worte falsch sind, sag es mir einfach. Wenn Ihre Dateihierarchie so angeordnet ist:

project\
    module_1.py 
    module_2.py

module_1.pydefiniert eine Funktion aufgerufen func_1(), module_2.py :

from module_1 import func_1

def func_2():
    func_1()

if __name__ == '__main__':
    func_2()

und wenn Sie python module_2.pyin cmd ausführen , wird ausgeführt, was func_1()definiert ist. So importieren wir normalerweise dieselben Hierarchiedateien. Aber wenn Sie schreiben from .module_1 import func_1in module_2.py, wird Python - Interpreter sagen No module named '__main__.module_1'; '__main__' is not a package. Um dies zu beheben, behalten wir einfach die Änderung bei, die wir gerade vorgenommen haben, und verschieben beide Module in ein Paket und lassen ein drittes Modul als Aufrufer ausführen module_2.py.

project\
    package_1\
        module_1.py
        module_2.py
    main.py

main.py :

from package_1.module_2 import func_2

def func_3():
    func_2()

if __name__ == '__main__':
    func_3()

Aber der Grund , warum wir eine hinzufügen , .bevor module_1in module_2.pyist , dass , wenn wir nicht tun , dass und ausführen main.py, wird Python - Interpreter sagen No module named 'module_1', dass ein wenig kompliziert ist, module_1.pyist direkt neben module_2.py. Nun lasse ich func_1()in module_1.pydo etwas:

def func_1():
    print(__name__)

das __name__zeichnet auf, wer func_1 aufruft. Jetzt behalten wir das .vorher module_1, laufen main.py, es wird gedruckt package_1.module_1, nicht module_1. Es zeigt an, dass sich derjenige, der anruft, func_1()in derselben Hierarchie wie befindet main.py, was .bedeutet, dass er module_1sich in derselben Hierarchie wie er module_2.pyselbst befindet. Wenn es also keinen Punkt gibt, main.pyder module_1an derselben Hierarchie wie er selbst erkennt, kann er erkennenpackage_1 , , aber nicht, was "darunter" ist.

Lassen Sie es uns jetzt etwas komplizierter machen. Sie haben ein config.iniund ein Modul definiert eine Funktion zum Lesen in derselben Hierarchie wie 'main.py'.

project\
    package_1\
        module_1.py
        module_2.py
    config.py
    config.ini
    main.py

Und aus irgendeinem unvermeidlichen Grund muss man es mit aufrufen module_2.py, damit es aus der oberen Hierarchie importiert werden kann. module_2.py :

 import ..config
 pass

Zwei Punkte bedeuten den Import aus der oberen Hierarchie (drei Punkte greifen auf die oberen als die oberen usw. zu). Jetzt rennen wir main.py, der Dolmetscher wird sagen : ValueError:attempted relative import beyond top-level package. Das "Top-Level-Paket" hier ist main.py. Nur weil sie config.pydaneben liegen main.py, befinden sie sich in derselben Hierarchie, config.pysind nicht "unter" main.pyoder werden nicht "angeführt" main.py, also ist es jenseits main.py. Um dies zu beheben, ist der einfachste Weg:

project\
    package_1\
        module_1.py
        module_2.py
    config.py
    config.ini
main.py

Ich denke, das stimmt mit dem Prinzip der Anordnung der Projektdateihierarchie überein. Sie sollten Module mit unterschiedlichen Funktionen in verschiedenen Ordnern anordnen und nur einen Top-Aufrufer im Freien lassen, und Sie können importieren, wie immer Sie wollen.

Findon Fassbender
quelle
-5

Dies funktioniert auch und ist viel einfacher als alles andere mit dem sysModul:

with open("C:/yourpath/foobar.py") as f:
    eval(f.read())
jgilley
quelle
1
Wenn OP einen Pfad fest codieren würde, könnten sie diesen Pfad trotzdem einfach in den PYTHONPATH einfügen. Ich denke, der Punkt ist, dies auf eine Weise zu tun, die einen Pfad nicht fest codiert, da er irgendwo anders brechen würde.
Matthew
-15

Rufen Sie mich übermäßig vorsichtig an, aber ich mache meine gerne portabler, weil es unsicher ist anzunehmen, dass sich Dateien auf jedem Computer immer an derselben Stelle befinden. Persönlich muss der Code zuerst den Dateipfad nachschlagen. Ich benutze Linux, damit meine so aussehen würde:

import os, sys
from subprocess import Popen, PIPE
try:
    path = Popen("find / -name 'file' -type f", shell=True, stdout=PIPE).stdout.read().splitlines()[0]
    if not sys.path.__contains__(path):
        sys.path.append(path)
except IndexError:
    raise RuntimeError("You must have FILE to run this program!")

Das ist natürlich so, es sei denn, Sie planen, diese zusammen zu verpacken. Aber wenn das der Fall ist, brauchen Sie sowieso nicht wirklich zwei separate Dateien.

SuperFamousGuy
quelle
11
Super ineffizient!
0xc0de
1
Dateien befinden sich auf jedem Computer immer an derselben Stelle, wenn ein relativer Pfad angegeben wird.
Sagar Hatekar