Werkzeug: Windows-Konsolenskripts, die vom Reloader aufgerufen werden

Erstellt am 13. Juni 2017  ·  14Kommentare  ·  Quelle: pallets/werkzeug

Ich verwende apistar auf Python 3 und stoße auf ein Problem, das mich zum Werkzeug-Reloader geführt hat.

(fresh) C:\Users\uskaxb07\PycharmProjects\testapi>apistar run
Starting up...
 * Restarting with stat
  File "C:\Users\uskaxb07\env\fresh\Scripts\apistar.exe", line 1
SyntaxError: Non-UTF-8 code starting with '\x90' in file C:\Users\uskaxb07\env\fresh\Scripts\apistar.exe on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

Das Entfernen von use_reloader aus dem Aufruf von run_simple() funktioniert. Nachdem ich ein paar Kommentare gelesen hatte, stellte ich fest, dass https://github.com/pallets/werkzeug/blob/master/werkzeug/_reloader.py#L118 einige Codierungen für latin1 durchführt, jedoch nur, wenn das Betriebssystem Windows und die Python-Version ist ist 2. Könnte dies den Nicht-UTF-8-Syntaxfehler verursachen, den ich in Python3 erhalte?

Alle 14 Kommentare

Gibt es ein kleines Beispiel, mit dem ich das reproduzieren kann? Ich bin mit der Verwendung von apistar nicht vertraut und verwende Windows nicht regelmäßig.

Ich habe mich noch ein bisschen damit beschäftigt. Das Problem liegt tatsächlich bei _get_args_for_reloading() . Diese Methode gibt Argumente zurück, die ['python.exe', 'apistar.exe', 'run'] die bei Übergabe an subprocess.call() diesen Fehler erzeugen. Es ist nicht anders, als python.exe apistar.exe run von der Befehlszeile aus aufzurufen.

Das Problem liegt also nicht an der Umgebungscodierung, wie ich ursprünglich dachte. Angesichts der Tatsache, dass dies in anderen werkzueg-basierten Frameworks sehr häufig vorkommt, denke ich, dass eine Änderung dieser Methode, um der Tatsache Rechnung zu tragen, dass sie über eine von Console_Script generierte .exe aufgerufen werden könnte, allen Windows-Benutzern zugute kommen würde.

Ich ändere den Titel der Ausgabe, um dies zu berücksichtigen.

Wenn diese Methode das sys.executable-Element von rv bei der Windows-Prüfung verworfen hat, ist das Neuladen erfolgreich:

def _get_args_for_reloading():
    """Returns the executable. This contains a workaround for windows
    if the executable is incorrectly reported to not have the .exe
    extension which can cause bugs on reloading.
    """
    rv = [sys.executable]
    py_script = sys.argv[0]
    if os.name == 'nt' and not os.path.exists(py_script) and \
       os.path.exists(py_script + '.exe'):
        py_script += '.exe'
        rv.pop()
    rv.append(py_script)
    rv.extend(sys.argv[1:])
    return rv

Ich freue mich, eine PR zu überprüfen, wenn Sie eine einreichen möchten.

Das würde ich auf jeden Fall gerne tun, aber ich stecke noch etwas fest, einen Test dafür zu schreiben. Ich kann nur sehen, dass dies mit der unittest.mock-Bibliothek und dem Patchen von sys.executable und os.name funktioniert, aber ich gehe davon aus, dass dies für Ihr Projekt nicht funktionieren würde, da es auch automatisierte Tests in 27 unterstützen muss. Irgendein Rat?

Und welche Verzweigungsstrategie wird hier verwendet? Widersprechen Pull-Requests für Issues dem aktuellen Wartungszweig?

Sie können von 0.12-Pflege abzweigen. Lassen Sie uns zuerst sehen, wie ein Patch aussieht, und dann den Test herausfinden.

Ich habe eine Pull-Anfrage gestellt. Es scheint, dass die Travis CI aus Gründen versagt, die nichts mit den von mir vorgenommenen Änderungen zu tun haben. Dies ist meine erste Pull-Anfrage, daher weiß ich nicht, wohin ich von hier aus gehen soll.

Dies geschieht, wenn Setuptools exe-Startprogramme installiert haben. Wenn Sie über – aktuelles – pip installieren, installiert es eine neue Art von exe-Launchern (von distlib ), die das Launcher-Skript in die exe in einer ZIP- runpy docs ).

Dies bedeutet nicht, dass dies nicht behoben werden sollte, aber es ist hilfreich zu wissen, falls Sie dies nicht reproduzieren können. Es wird immer noch passieren, wenn Sie Flask beispielsweise im Entwicklungsmodus ( pip install -e ) installieren.

@androiddrew @davidism Gibt es ein Update zu dieser PR?

@segevfiner kannst du deinem letzten Kommentar etwas mehr Details hinzufügen? Schlagen Sie vor, dass wir die Ursache wahrscheinlich in Setuptools und nicht in Flask beheben sollten?

@ewpete Die Hauptursache ist, dass bei der Verwendung von setuptools generierten Launchern
sys.argv[0] ist nicht als Python-Skript ausführbar, da es das
Launcher-exe. Das eigentliche Skript wird wie die exe mit - "-script" benannt
angehängt und die exe lädt und führt sie aus.

Beachten Sie, dass die exe direkt ausgeführt werden kann (Und so ist ein Python-Skript
mit Shebang, von dem ich glaube, dass Setuptools auf Unices generiert). Aber
Dies ist für einfache Python-Skripte unter Windows unzuverlässig (Wenn die
pylauncher ist nicht installiert), da es mit dem beliebigen Python gestartet wird
die mit .py-Dateien in der Registrierung verknüpft ist, die unterschiedlich sein können
als das aktuelle Python, das wir verwenden. Und das gilt natürlich auch für
jedes beliebige Python-Skript, von dem aus wir aufgerufen werden könnten, was möglicherweise nicht einmal der Fall ist
ausführbar.

pip installiert stattdessen (über distlib) eine neue Art von exe-Launcher, der die
generiertes Launcher-Skript, das in eine Zip-Datei am Ende des
ausführbar. Dies wird als ZIP-Datei mit einem __main__.py-Skript (A
zipapp) und kann zur Ausführung direkt an Python übergeben werden.

Um dies in den Setuptools zu beheben, müssen Sie einen ähnlichen/gleichen Typ erzeugen
Launcher in den Setuptools. Und im Sinne von http://xkcd.com/1172/ , dies
wird wahrscheinlich Code brechen, der die Setuptools-Startprogramme und -versuche erwartet
Verwenden Sie die Dateien "*-script.py", um das Problem zu umgehen. ich habe nicht nachgeschaut
ob es bereits ein Problem/PR diesbezüglich gibt.

Es ist wahrscheinlich in Ordnung, hier einen kleinen Workaround zu haben, damit Werkzeug
reloader funktioniert auch in Gegenwart des aktuellen Stils der Setuptools
Trägerraketen. Aber das ist wirklich Sache der Projektbetreuer.

בתאריך 28 בנוב' 2017 20:46,‏ "ewpete" [email protected] :

@androiddrew https://github.com/androiddrew @davidism
https://github.com/davidism Gibt es ein Update zu dieser PR?

@segevfiner https://github.com/segevfiner kannst du noch ein bisschen mehr hinzufügen
Detail zu Ihrem letzten Kommentar? Schlagen Sie vor, dass wir?
wahrscheinlich die Ursache in Setuptools beheben, im Gegensatz zu Flask?


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/pallets/werkzeug/issues/1136#issuecomment-347623921 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AXlg_8OSR3NdbPJzM87dyKPUAA9NpXJ6ks5s7FT7gaJpZM4N5Fcb
.das

@ewpete Das war meine erste PR. Ich habe mein Bestes getan, um Tests zu schreiben, dem Entwicklerleitfaden zu folgen und die PR zu platzieren. Ich hatte nicht viele Anweisungen dazu, aber ich habe die vorgeschlagenen Änderungen aus den PR-Kommentaren vorgenommen. Ich hielt es für vollständig, hörte aber nie wieder, ob es den Erwartungen des Projektteams entsprach. Seitdem habe ich es mir nicht mehr angeschaut, und ich weiß nicht, was die Leute damit machen wollen.

Ich habe sehr begrenzte Zeit für mehrere Projekte. Keine Sorge, habe das nicht vergessen.

@davidism Vielen Dank, nicht nur für

Dies ist zwar immer noch nicht zusammengeführt, aber eine mögliche vorübergehende Lösung besteht darin, die Funktion _get_args_for_reloading() irgendwo vor ihrer Verwendung zu monkeypatchen. Im Falle eines Flask-Skripts hilft es, dies irgendwo am Anfang einer manage.py Datei hinzuzufügen:

import werkzeug._reloader
import os, sys

def _get_args_for_reloading():
    rv = [sys.executable]
    py_script = sys.argv[0]
    if os.name == 'nt' and not os.path.exists(py_script) and \
       os.path.exists(py_script + '.exe'):
        py_script += '.exe'
    if os.path.splitext(rv[0])[1] == '.exe' and os.path.splitext(py_script)[1] == '.exe':
        rv.pop()
    rv.append(py_script)
    rv.extend(sys.argv[1:])
    return rv
werkzeug._reloader._get_args_for_reloading = _get_args_for_reloading
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen