Müde von sys.path Hacks?
Es gibt viele sys.path.append
-hacks, aber ich habe einen alternativen Weg gefunden, um das Problem in der Hand zu lösen.
Zusammenfassung
- Wickeln Sie den Code in einen Ordner (zB
packaged_stuff
)
- Verwenden Sie das Erstellungsskript,
setup.py
in dem Sie setuptools.setup () verwenden .
- Pip installiert das Paket im bearbeitbaren Zustand mit
pip install -e <myproject_folder>
- Importieren mit
from packaged_stuff.modulename import function_name
Konfiguration
Der Ausgangspunkt ist die von Ihnen bereitgestellte Dateistruktur, die in einen Ordner mit dem Namen eingeschlossen ist myproject
.
.
└── myproject
├── api
│ ├── api_key.py
│ ├── api.py
│ └── __init__.py
├── examples
│ ├── example_one.py
│ ├── example_two.py
│ └── __init__.py
├── LICENCE.md
├── README.md
└── tests
├── __init__.py
└── test_one.py
Ich werde den .
Stammordner aufrufen und in meinem Beispiel befindet er sich unter C:\tmp\test_imports\
.
api.py.
Verwenden wir als Testfall die folgende ./api/api.py
def function_from_api():
return 'I am the return value from api.api!'
test_one.py
from api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
Versuchen Sie, test_one auszuführen:
PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
File ".\myproject\tests\test_one.py", line 1, in <module>
from api.api import function_from_api
ModuleNotFoundError: No module named 'api'
Auch der Versuch, relative Importe durchzuführen, funktioniert nicht:
Die Verwendung from ..api.api import function_from_api
würde dazu führen
PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
File ".\tests\test_one.py", line 1, in <module>
from ..api.api import function_from_api
ValueError: attempted relative import beyond top-level package
Schritte
- Erstellen Sie eine setup.py-Datei im Stammverzeichnis
Der Inhalt für setup.py
wäre *
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
- Verwenden Sie eine virtuelle Umgebung
Wenn Sie mit virtuellen Umgebungen vertraut sind, aktivieren Sie eine und fahren Sie mit dem nächsten Schritt fort. Die Verwendung von virtuellen Umgebungen sind nicht unbedingt erforderlich, aber sie werden wirklich Sie auf lange Sicht helfen (wenn Sie mehr als 1 Projekt laufenden haben ..). Die grundlegendsten Schritte sind (im Stammordner ausführen)
- Erstellen Sie eine virtuelle Umgebung
- Aktivieren Sie die virtuelle Umgebung
source ./venv/bin/activate
(Linux, macOS) oder ./venv/Scripts/activate
(Win)
Um mehr darüber zu erfahren, googeln Sie einfach "python virtual env tutorial" oder ähnliches. Sie benötigen wahrscheinlich nie andere Befehle als das Erstellen, Aktivieren und Deaktivieren.
Nachdem Sie eine virtuelle Umgebung erstellt und aktiviert haben, sollte Ihre Konsole den Namen der virtuellen Umgebung in Klammern angeben
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
und dein Ordnerbaum sollte so aussehen **
.
├── myproject
│ ├── api
│ │ ├── api_key.py
│ │ ├── api.py
│ │ └── __init__.py
│ ├── examples
│ │ ├── example_one.py
│ │ ├── example_two.py
│ │ └── __init__.py
│ ├── LICENCE.md
│ ├── README.md
│ └── tests
│ ├── __init__.py
│ └── test_one.py
├── setup.py
└── venv
├── Include
├── Lib
├── pyvenv.cfg
└── Scripts [87 entries exceeds filelimit, not opening dir]
- pip Installieren Sie Ihr Projekt im bearbeitbaren Zustand
Installieren Sie Ihr Top-Level-Paket myproject
mit pip
. Der Trick besteht darin, -e
bei der Installation das Flag zu verwenden . Auf diese Weise wird es in einem bearbeitbaren Zustand installiert, und alle an den .py-Dateien vorgenommenen Änderungen werden automatisch in das installierte Paket aufgenommen.
Führen Sie im Stammverzeichnis aus
pip install -e .
(Beachten Sie den Punkt, er steht für "aktuelles Verzeichnis")
Sie können auch sehen, dass es mithilfe von installiert wird pip freeze
(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0
- Fügen Sie
myproject.
Ihren Importen hinzu
Beachten Sie, dass Sie myproject.
nur Importe hinzufügen müssen , die sonst nicht funktionieren würden. Importe, die ohne setup.py
& pip install
funktionierten, funktionieren weiterhin einwandfrei. Siehe ein Beispiel unten.
Testen Sie die Lösung
Testen wir nun die Lösung mit api.py
den oben test_one.py
definierten und unten definierten.
test_one.py
from myproject.api.api import function_from_api
def test_function():
print(function_from_api())
if __name__ == '__main__':
test_function()
Test ausführen
(venv) PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
I am the return value from api.api!
* Weitere ausführliche Beispiele für setup.py finden Sie in den setuptools-Dokumenten .
** In Wirklichkeit können Sie Ihre virtuelle Umgebung überall auf Ihrer Festplatte platzieren.
sys.path
Hacks zu überspringen und die einzige tatsächliche Lösung zu lesen , die bisher veröffentlicht wurde (nach 7 Jahren!).