Problem
PEP8 hat eine Regel zum Einfügen von Importen an den Anfang einer Datei:
Importe werden immer am Anfang der Datei platziert, direkt nach Modulkommentaren und Dokumentzeichenfolgen sowie vor Modulglobalen und -konstanten.
In bestimmten Fällen möchte ich jedoch möglicherweise Folgendes tun:
import sys
sys.path.insert("..", 0)
import my_module
In diesem Fall kennzeichnet das pep8
Befehlszeilenprogramm meinen Code:
Import auf E402-Modulebene nicht oben in der Datei
Was ist der beste Weg, um die PEP8-Konformität mit sys.path
Änderungen zu erreichen ?
Warum
Ich habe diesen Code, weil ich der Projektstruktur folge, die im Per Anhalter durch Python angegeben ist .
In diesem Handbuch wird vorgeschlagen, dass ich einen my_module
Ordner habe, der von einem tests
Ordner getrennt ist und sich beide im selben Verzeichnis befinden. Wenn ich zugreifen möchten my_module
aus tests
, ich glaube , ich muss hinzufügen , ..
um diesys.path
quelle
setup.py
und installierst sie tatsächlichmy_module
zum Testen?Antworten:
Oft habe ich mehrere Dateien mit Tests in einem Unterverzeichnis
foo/tests
meines Projekts, während sich die Module, in denen ich teste, befindenfoo/src
. Um die Testsfoo/tests
ohne Importfehler auszuführen, erstelle ich eine Dateifoo/tests/pathmagic.py
, die so aussieht."""Path hack to make tests work.""" import os import sys bp = os.path.dirname(os.path.realpath('.')).split(os.sep) modpath = os.sep.join(bp + ['src']) sys.path.insert(0, modpath)
In jeder Testdatei verwende ich dann
import pathmagic # noqa
als erster Import. Die „noqa“ Kommentar verhindert
pycodestyle
/pep8
von etwa einem nicht verwendeten Import beschweren.quelle
pathmagic
werden, das importiert werden kann. Die meisten Python-Testläufer gehen davon aus, dass es sich bei Ihren Tests um eine Sammlung von Dateien handelt, die nicht aktiviert sind. Einesys.path
Änderung, die zu Problemen führen kann, zeigt, wiepytest
mit diesen Problemen umgegangen wird. Docs.pytest.org/en/latest/…Wenn es nur wenige Importe gibt, können Sie PEP8 in diesen
import
Zeilen einfach ignorieren :import sys sys.path.insert("..", 0) import my_module # noqa: E402
quelle
# noqa: E402
zum Beispiel anzugeben . ( Quelle )Es gibt noch eine andere Problemumgehung.
import sys ... all your other imports... sys.path.insert("..", 0) try: import my_module except: raise
quelle
try
Körper und alles andere (was nicht davon abhängt) oben zu setzen.if 1: import module
Ich habe gerade mit einer ähnlichen Frage gekämpft und ich denke, ich habe eine etwas schönere Lösung gefunden als die akzeptierte Antwort.
Erstellen Sie ein
pathmagic
Modul, das die eigentliche Manipulation von sys.path ausführt, die Änderung jedoch in einem Kontextmanager vornimmt :"""Path hack to make tests work.""" import os import sys class context: def __enter__(self): bp = os.path.dirname(os.path.realpath('.')).split(os.sep) modpath = os.sep.join(bp + ['src']) sys.path.insert(0, modpath) def __exit__(self, *args): pass
Dann tun Sie in Ihren Testdateien (oder wo immer Sie dies benötigen):
import pathmagic with pathmagic.context(): import my_module # ...
Auf diese Weise erhalten Sie keine Beschwerden von flake8 / pycodestyle, Sie benötigen keine speziellen Kommentare und die Struktur scheint sinnvoll zu sein.
Erwägen Sie für zusätzliche Sauberkeit, den Pfad im
__exit__
Block tatsächlich zurückzusetzen. Dies kann jedoch zu Problemen bei verzögerten Importen führen (wenn Sie den Modulcode außerhalb des Kontexts platzieren), sodass sich die Mühe möglicherweise nicht lohnt.BEARBEITEN : Ich habe gerade einen viel einfacheren Trick bei der Beantwortung einer anderen Frage gesehen : Fügen Sie
assert pathmagic
unter Ihren Importen hinzu, um dennoqa
Kommentar zu vermeiden .quelle
__exit__
Block wirklich ordnungsgemäß durchzuführen, müsste lediglich der hinzugefügte Pfad entfernt werden (sofern er noch vorhanden ist), da durch Wiederherstellen des gesamten vorherigen Werts auf den Stand bei Eingabe des Kontexts auch andere Änderungen rückgängig gemacht werden könnten wurden aus irgendeinem Grund von einem anderen Code (der im selben Kontext ausgeführt wird) dazu gebracht.pathmagic.context()
beliebig oft aufgerufen werden kann (zB wenn alle Tests ausgeführt werden). Das Zurücksetzen ist ebenfalls problematisch: Jeder spätere Import (z. B. bei Bedarf) kann fehlschlagen.Haben Sie bereits Folgendes versucht:
import sys from importlib import import_module sys.path.insert("..", 0) # import module my_mod = import_module('my_module') # get method or function from my_mod my_method = getattr(my_mod , 'my_method')
quelle
Um pep8 zu erfüllen, sollten Sie Ihren Projektpfad in den Python-Pfad aufnehmen, um relative / absolute Importe durchzuführen.
Zu diesem Zweck können Sie sich diese Antwort ansehen: Fügen Sie PYTHONPATH dauerhaft ein Verzeichnis hinzu
quelle