Frage Muss ich in jedem Skript mein Projektverzeichnis zum Systempfad hinzufügen, um eine Funktion aus einem anderen Verzeichnis zu importieren?


Ich versuche, ein Data-Science-Projekt gut organisiert zu halten, also habe ich ein Verzeichnis in meinem erstellt src Verzeichnis aufgerufen utils das enthält eine Datei namens helpers.py, die einige Hilfsfunktionen enthält, die in vielen Skripten verwendet werden. Was ist die beste Vorgehensweise für das Importieren? func_name von src/utils/helpers.py in eine Datei in einem völlig anderen Verzeichnis, wie z src/processing/clean_data.py?

Aha Antworten zu dieser Frage, und ich habe eine Lösung implementiert, die funktioniert, aber das fühlt sich hässlich an:

 sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))

Mache ich das richtig? Muss ich das zu jedem Skript hinzufügen, das importiert werden soll func_name, mögen train_model.py?

Meine aktuelle Projektordnerstruktur:

myproject
    /notebooks
        notebook.ipynb
    /src
        /processing
            clean_data.py
        /utils
            helpers.py
        /models
            train_model.py
        __init__.py

Beispieldateien:

# clean_data.py

import os
import sys

sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
from src.utils.helpers import func_name

func_name()


# helpers.py

def func_name():
    print('I'm a helper function.')

9
2018-02-13 04:28


Ursprung


Antworten:


Der richtige Weg ist es zu verwenden __init__.py, setup.py und das setuptools Python-Paket:

myPackage/
    myPackage/
        __init__.py
    setup.py

Dies Verknüpfung hat alle Schritte.


5
2018-02-13 04:36



Lassen Sie mich zuerst die Unterschiede zwischen a Python-Modul & ein Python-Paket damit wir beide auf der gleichen Seite sind.


Ein Modul ist eine einzelne .py-Datei (oder Dateien) die unter einem Import importiert und verwendet werden.

import aModuleName # Here 'aModuleName' is just a regular .py file.

Wohingegen, ein Paket ist a Sammlung von Modulen in Verzeichnissen, die eine Pakethierarchie ergeben. Ein Paket enthält ein distinct __init__.py Datei.

from aPackageName import aModuleName # Here 'aPackageName` is a folder with a `__init__.py` file # and 'aModuleName', which is just a regular .py file.


Daher, wenn wir ein Projektverzeichnis haben proj-dir der folgenden Struktur

proj-dir --|--__init__.py --package1 --|--__init__.py --|--module1.py --package2 --|--__init__.py --|--module2.py

 Beachten Sie, dass ich auch eine leere hinzugefügt habe __init__.py in die proj-dir selbst das macht es auch zu einem Paket.

 Wenn Sie nun ein Python-Objekt importieren möchten Modul2 von Paket2 in Modul 1 von Paket1, dann ist die einführen Anweisung in der Datei module1.py wäre

from package2.module2 import object2 # if you were to import the entire module2 then, from package2 import module2

Ich hoffe, diese einfache Erklärung verdeutlicht Ihre Zweifel am Mechanismus von Python-Importen und löst das Problem. Wenn nicht, dann kommentiere hier.


4
2018-02-23 06:49



Lassen Sie mich zuerst klarstellen, dass das Importieren eines ganzen Moduls, wenn Sie einen Teil davon verwenden, keine gute Idee ist. Stattdessen können Sie verwenden from um spezifische Funktionen unter einer Bibliothek / einem Paket zu importieren. Auf diese Weise machen Sie Ihr Programm in Bezug auf Speicher und Leistung effizient.

Um mehr zu wissen, beziehen Sie sich auf diese:

  1. 'Importmodul' oder 'aus Modulimport'
  2. Unterschied zwischen Import und von

Net lasst uns in die Lösung schauen.

Bevor Sie mit der Lösung beginnen, lassen Sie mich die Verwendung von __init__.py Datei. Es sagt nur dem Python-Interpreter, dass der * .py die dort vorhandenen Dateien sind importierbar, dh sie sind Module und sind / vielleicht ein Teil eines Pakets.

Also, wenn Sie N keine Unterverzeichnisse haben, müssen Sie setzen __init__.py Datei in alle diese Unterverzeichnisse, so dass sie auch importiert werden können. Innerhalb __init__.py Datei können Sie auch einige zusätzliche Informationen hinzufügen, wie welcher Pfad enthalten sein sollte, Standardfunktionen, Variablen, Gültigkeitsbereich, etc. Um darüber zu wissen, googeln Sie einfach __init__.pyDatei oder nehmen Sie eine Python-Bibliothek und gehen Sie durch das gleiche __init__.py Datei darüber zu wissen. (Hier liegt die Lösung)

Mehr Info:

  1. Module
  2. Sei pythisch

Also wie gesagt von @ Sushant Chaudhary Ihre Projektstruktur sollte wie folgt aussehen

proj-dir
 --|--__init__.py
   --package1
     --|--__init__.py
     --|--module1.py
   --package2
     --|--__init__.py
     --|--module2.py

So, jetzt, wenn ich lege __init__.py Datei unter meinem Verzeichnis wie oben, Will   Es ist importierbar und funktioniert gut?

Ja und nein.

Ja :

Wenn Sie die Module in diesem Projekt- / Paketverzeichnis importieren. zum Beispiel in deinem Fall
 Sie importieren package1.module1 in pakage2.module2 als from package1 import module1.

Hier musst du das importieren Basis dir in den Untermodulen, Warum? Das Projekt wird ordnungsgemäß ausgeführt, wenn Sie das Modul von demselben Ort ausführen. d. h. innerhalb von package2 als python module2.py, Aber wird werfen ModuleNotFoundError Wenn Sie das Modul aus einem anderen Verzeichnis ausführen. d. h .: jeder andere Pfad außer Paket2 zum Beispiel unter proj-dir als python package1/module1.py. Das passiert in Ihrem Fall. Sie führen das Modul aus dem Projektverzeichnis aus.

So, wie das zu beheben?

  1. Sie müssen den Pfad basedir zum Systempfad in module1.py hinzufügen

    from sys import path dir_path = "/absolute/path/to/proj-dir" sys.path.insert(0, dir_path)

  2. Sie müssen alle Untermodulpfade hinzufügen __init__.py Datei unter proj-dir.

Beispielsweise:

#__init__.py under lxml
# this is a package

def get_include():
    """
    Returns a list of header include paths (for lxml itself, libxml2
    and libxslt) needed to compile C code against lxml if it was built
    with statically linked libraries.
    """
    import os
    lxml_path = __path__[0]
    include_path = os.path.join(lxml_path, 'includes')
    includes = [include_path, lxml_path]

    for name in os.listdir(include_path):
        path = os.path.join(include_path, name)
        if os.path.isdir(path):
            includes.append(path)

    return includes

Dies ist das __init__.py Datei von Lxml (eine Python-Bibliothek zum Parsen von HTML, XML-Daten). Sie können sich darauf beziehen __init__.py Datei unter Python-Bibliotheken mit Untermodulen.ex (os, sys). Hier habe ich erwähnt Lxml weil ich dachte, es wird leicht für dich zu verstehen sein. Sie können sogar überprüfen __init__.py Datei unter anderen Bibliotheken / Paketen. Jeder hat seine eigene Art, den Pfad für Submodule zu definieren.

Nein

Wenn Sie versuchen, Module außerhalb des Verzeichnisses zu importieren. Dann müssen Sie den Modulpfad exportieren, so dass andere Module sie in Umgebungsvariablen finden können. Dies kann direkt durch Anhängen des absoluten Pfades des Basisverzeichnisses erfolgen PYTHONPATH oder zu PFAD.

Mehr wissen:

  1. PATH-Variablen im Betriebssystem
  2. PYTHONPATH-Variable

Um Ihr Problem zu lösen, fügen Sie die Pfade zu allen Untermodulen hinzu __init__.py Datei unter proj-dir und füge das hinzu / absolut / Pfad / zu / proj-dir entweder um zu PYTHONPATH oder PATH.

Hoffe, die Antwort erklärt Ihnen die Verwendung von __init__.py und löst dein Problem.


1
2018-03-01 05:22



Unter Linux können Sie einfach den Pfad zum übergeordneter Ordner von deinem src Verzeichnis zu ~/.local/lib/python3.6/site-packages/my_modules.pth. Sehen Verwenden von PTH-Dateien. Sie können dann Module importieren src von überall auf Ihrem System.

NB1: Ersetzen python3.6 von jeder Version von Python, die Sie verwenden möchten.

NB2: Wenn Sie Python2.7 verwenden (weiß nicht für andere Versionen), müssen Sie erstellen __init__.py (leere) Dateien in src/ und src/utils.

NB3: Jeder Name.pth Datei ist in Ordnung für my_modules.pth.


1
2018-03-01 09:57



Ja, Sie können nur Code von installierten Paketen oder von Dateien in Ihrem Arbeitsverzeichnis oder in Unterverzeichnissen importieren.


0
2018-02-24 15:27



So wie ich es sehe, wäre Ihr Problem gelöst, wenn Sie Ihr Modul oder Paket installiert hätten, wie ein anderes Paket, das installiert und dann importiert wird (numpy, xml, json usw.)

Ich habe auch ein Paket, das ich ständig in allen meinen Projekten verwende, ultitiliesund ich weiß, es ist ein Schmerz beim Importieren.

Hier finden Sie eine Beschreibung, wie Sie eine Python-Anwendung so packen, dass sie pip-installierbar wird: https://marthall.github.io/blog/how-to-package-a-python-app/


0
2018-03-01 12:36



  • Navigieren Sie zu Ihrem Python-Installationsordner

  • Navigiere zu lib

  • Navigieren Sie zu Site-Paketen

  • Erstelle eine neue Datei namens any_thing_you_want.pth

  • Art .../src/utils/helpers.py innerhalb dieser Datei mit Ihrem bevorzugten Texteditor

Hinweis: Die Ellipse vorher scr/utils/helpers.py sieht etwa so aus: C:/Users/blahblahblah/python_folders/scr...  <- SIE BENÖTIGEN DIESES!

Dies ist ein billiger Ausweg, aber es hält den Code sauber und ist am wenigsten kompliziert. Der Nachteil ist, dass example.phth für jeden Ordner, in dem sich Ihre Module befinden, sie benötigt. Upside: funktioniert mit Windows bis hin zu Windows 10


0
2018-03-01 23:26