Ich hatte das gleiche Problem und fand diese Frage. Aufgrund der Antworten hier konnte ich mein Problem jedoch nicht lösen. Ich fing an, den Cpython-Code zu debuggen und dachte, ich könnte einen Fehler entdecken. Daher habe ich ein Problem im Python Issue Tracker geöffnet.
Mein Fehler war, dass ich nicht verstanden habe, dass Py_SetPathalle abgeleiteten Wege frei sind. Man muss also alle Pfade setzen, wenn man diese Funktion aufruft.
Zum Abschluss habe ich auch den wichtigsten Teil des Gesprächs unten kopiert.
Mein ursprünglicher Problemtext
Ich habe die Quelle von CPython 3.7.3 selbst unter Windows mit Visual Studio 2017 zusammen mit einigen Paketen wie z. B. numpy kompiliert. Wenn ich den Python Interpreter starte, kann ich numpy importieren und verwenden. Wenn ich jedoch dasselbe Skript über die C-API ausführe, erhalte ich eine ModuleNotFoundError.
Als erstes habe ich überprüft, ob sich numpy in meinem Site-Packages-Verzeichnis befindet und tatsächlich ein Ordner mit dem Namen numpy-1.16.2-py3.7-win-amd64.egg vorhanden ist. (Sinnvoll, da der Python-Interpreter numpy finden kann)
Als nächstes habe ich einige Informationen über die Variable sys.path erhalten, die beim Ausführen des Skripts über die C-API erstellt wurde.
C:\Work\build\product\python37.zip
C:\Work\build\product\DLLs
C:\Work\build\product\lib
C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2017\PROFESSIONAL\COMMON7\IDE\EXTENSIONS\TESTPLATFORM
C:\Users\rvq\AppData\Roaming\Python\Python37\site-packages
Als ich den Inhalt von sys.path untersuchte, bemerkte ich zwei Dinge.
C:\Work\build\product\python37.ziphat den richtigen Weg ' C:\Work\build\product\'. Es gab einfach keine Zip-Datei. Alle meine Dateien und Verzeichnisse wurden entpackt. Also habe ich die Dateien in ein Archiv namens python37.zip gezippt und dadurch den Importfehler behoben.
C:\Users\rvq\AppData\Roaming\Python\Python37\site-packagesist falsch, sollte es sein, C:\Work\build\product\Lib\site-packagesaber ich weiß nicht, wie dieser falsche Pfad erstellt wird.
Das nächste, was ich versuchte, war Py_SetPath(L"C:/Work/build/product/Lib/site-packages")vor dem Anruf zu verwenden Py_Initialize(). Dies führte zu
Schwerwiegender Python-Fehler 'Dateisystemcodierung kann nicht geladen werden' ModuleNotFoundError: Kein Modul mit dem Namen 'encodings'
Ich habe ein minimales C ++ - Projekt mit genau diesen beiden Aufrufen erstellt und mit dem Debuggen von Cpython begonnen.
int main()
{
Py_SetPath(L"C:/Work/build/product/Lib/site-packages");
Py_Initialize();
}
Ich verfolgte den Anruf von Py_Initialize()bis zum Anruf von
static int
zipimport_zipimporter___init___impl(ZipImporter *self, PyObject *path)
innerhalb von zipimport.c
Der Kommentar über dieser Funktion besagt Folgendes:
Erstellen Sie eine neue Zipimporter-Instanz. 'archivepath' muss ein pfadähnliches Objekt zu einer Zip-Datei oder zu einem bestimmten Pfad innerhalb einer Zip-Datei sein. Beispielsweise kann es sich um '/tmp/myimport.zip' oder '/tmp/myimport.zip/mydirectory' handeln, wenn mydirectory ein gültiges Verzeichnis im Archiv ist. 'ZipImportError' wird ausgelöst, wenn 'archivepath' nicht auf ein gültiges Zip-Archiv verweist. Das Attribut 'archive' des zipimporter-Objekts enthält den Namen der Ziel-Zip-Datei.
Für mich scheint die C-API zu erwarten, dass der mit Py_SetPath festgelegte Pfad ein Pfad zu einer Zip-Datei ist. Ist das erwartetes Verhalten oder ist es ein Fehler? Wenn es sich nicht um einen Fehler handelt, gibt es eine Möglichkeit, dies zu ändern, damit auch Verzeichnisse erkannt werden können?
PS: Der ModuleNotFoundError ist bei Verwendung von Python 3.5.2+, der Version, die ich zuvor in meinem Projekt verwendet habe, bei mir nicht aufgetreten. Ich habe auch überprüft, ob ich Umgebungsvariablen für PYTHONHOME oder PYTHONPATH festgelegt habe, aber keine davon auf meinem System gesehen.
Antworten
Dies ist wahrscheinlich mehr als alles andere ein Dokumentationsfehler. Wir sind gerade dabei, die Initialisierung neu zu gestalten, daher ist es ein guter Zeitpunkt, dieses Feedback beizutragen.
Die kurze Antwort lautet, dass Sie sicherstellen müssen, dass Python das Lib/encodingsVerzeichnis finden kann , indem Sie normalerweise die Standardbibliothek einfügen sys.path. Py_SetPathlöscht alle abgeleiteten Pfade, daher müssen Sie alle Stellen angeben, an denen Python suchen soll. (Die Regeln, nach denen Python automatisch aussieht, sind kompliziert und variieren je nach Plattform. Dies möchte ich unbedingt korrigieren.)
Pfade, die nicht existieren, sind in Ordnung, und das ist die Zip-Datei. Sie können die stdlib in eine Zip-Datei einfügen. Sie wird automatisch gefunden, wenn Sie sie als Standardpfad angeben. Sie können sie jedoch auch entpackt lassen und auf das Verzeichnis verweisen.
Ein vollständiger Überblick über das Einbetten ist mehr als ich bereit bin, auf meinem Telefon zu tippen. Hoffentlich ist das genug, um dich jetzt zum Laufen zu bringen.