Werkzeug: Windows console_scripts appelé depuis le rechargeur

Créé le 13 juin 2017  ·  14Commentaires  ·  Source: pallets/werkzeug

J'exécute apistar sur python 3 et je rencontre un problème qui m'a conduit au rechargement werkzeug.

(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

La suppression du use_reloader de l'appel à run_simple() fonctionne. Après avoir creusé quelques commentaires, j'ai trouvé que https://github.com/pallets/werkzeug/blob/master/werkzeug/_reloader.py#L118 encodait en latin1 mais uniquement lorsque le système d'exploitation est Windows et la version python est 2. Cela pourrait-il être à l'origine de l'erreur de syntaxe non UTF-8 que je reçois en python3 ?

Tous les 14 commentaires

Y a-t-il un petit exemple que je peux utiliser pour reproduire cela? Je ne suis pas habitué à utiliser apistar et n'utilise pas régulièrement Windows.

J'ai creusé un peu plus loin. Le problème est en fait avec _get_args_for_reloading() . Cette méthode renvoie des arguments qui sont ['python.exe', 'apistar.exe', 'run'] qui, lorsqu'ils sont passés à subprocess.call() génèrent cette erreur. Ce n'est pas différent de l'appel de python.exe apistar.exe run partir de la ligne de commande.

Le problème ne vient donc pas de l'encodage de l'environnement comme je le pensais au départ. Étant donné que ce serait un phénomène très courant dans d'autres frameworks basés sur werkzueg, je pense qu'une modification de cette méthode pour tenir compte du fait qu'elle pourrait être appelée via un .exe généré par console_script profiterait à tous les utilisateurs de Windows.

Je change le titre du problème pour en tenir compte.

Si cette méthode supprime l'élément sys.executable de rv dans la vérification de Windows, le rechargement est réussi :

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

Je suis heureux d'examiner un PR si vous souhaitez en soumettre un.

J'aimerais bien, mais je suis un peu coincé sur l'écriture d'un test pour cela. Je ne vois que cela fonctionner avec la bibliothèque unittest.mock et patcher sys.executable et os.name, mais je suppose que cela ne fonctionnerait pas pour votre projet car il doit également prendre en charge les tests automatisés dans 27. Aucun conseil?

Quelle est également la stratégie de branchement utilisée ici ? Les demandes d'extraction de problèmes vont-elles à l'encontre de la branche de maintenance actuelle ?

Vous pouvez passer de 0.12-maintenance. Voyons d'abord à quoi ressemble un patch, puis découvrons le test.

J'ai soumis une demande de tirage. Il semble que le Travis CI échoue cependant pour des raisons sans rapport avec les modifications que j'ai apportées. C'est ma première Pull Request donc je ne sais pas où aller à partir d'ici.

Cela se produira lorsque setuptools sera installé sur les lanceurs exe. Si vous installez via - à jour - pip, il installe un nouveau type de lanceurs d'exe (depuis distlib ) qui regroupent le script du lanceur dans l'exe à l'intérieur d'un zip que Python peut exécuter directement ( runpy docs ).

Cela ne signifie pas que cela ne devrait pas être corrigé, mais il est utile de le savoir au cas où vous ne pourriez pas le reproduire. Cela arrivera toujours si vous installez Flask en mode développement ( pip install -e ) par exemple.

@androiddrew @davidism une mise à jour sur ce PR ?

@segevfiner pouvez-vous ajouter un peu plus de détails à votre commentaire le plus récent ? Suggérez-vous que nous devrions probablement corriger la cause première dans setuptools plutôt que dans Flask ?

@ewpete La cause première est que lors de l'utilisation des lanceurs générés par setuptools,
le sys.argv[0] n'est pas exécutable en tant que script Python car c'est le
lanceur exe. Le script réel est nommé comme l'exe avec - "-script"
ajouté et l'exe le charge et l'exécute.

Notez que l'exe peut être exécuté directement (ainsi qu'un script Python
avec shebang qui, je crois, est ce que setuptools génère sur les unices). Mais
le faire pour des scripts Python simples sous Windows n'est pas fiable (lorsque le
pylauncher n'est pas installé), car il se lancera avec le Python arbitraire
qui est associé aux fichiers .py dans le registre, ce qui peut être différent
que le Python actuel que nous utilisons. Et, bien sûr, il en va de même pour
tout script Python aléatoire à partir duquel nous pourrions être invoqués, ce qui pourrait même ne pas être
exécutable.

pip installe à la place (via distlib) un nouveau type de lanceur d'exe qui a le
script de lancement généré ajouté à l'intérieur d'un zip à la fin du
exécutable. Cela sera détecté comme un fichier zip avec un script __main__.py (A
zipapp) et peut être transmis directement à Python pour exécution.

Pour résoudre ce problème dans setuptools, il faudra générer un kindbof similaire/même
lanceurs dans setuptools. Et dans l'esprit de http://xkcd.com/1172/ , ce
va probablement casser le code qui attend les lanceurs setuptools et essaie
en utilisant les fichiers "*-script.py" pour contourner le problème. je n'ai pas vérifié
s'il y a déjà un problème/pr à ce sujet.

C'est probablement bien d'avoir une petite solution de contournement ici pour que Werkzeug
reloader fonctionne même en présence du style actuel des setuptools
lanceurs. Mais cela dépend vraiment des mainteneurs du projet.

28 ' 2017 20:46,‏ "ewpete" [email protected] :

@androiddrew https://github.com/androiddrew @davidism
https://github.com/davidism aucune mise à jour sur ce PR ?

@segevfiner https://github.com/segevfiner pouvez-vous en ajouter un peu plus
détail de votre commentaire le plus récent ? Suggérez-vous que nous devrions
probablement corriger la cause première dans setuptools plutôt que dans Flask ?

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/pallets/werkzeug/issues/1136#issuecomment-347623921 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AXlg_8OSR3NdbPJzM87dyKPUAA9NpXJ6ks5s7FT7gaJpZM4N5Fcb
.la

@ewpete C'était ma première RP. J'ai fait de mon mieux pour écrire des tests, suivre le guide de développement et placer le PR. Je n'avais pas beaucoup d'indications sur la façon de procéder, mais j'ai apporté les modifications suggérées à partir des commentaires des relations publiques. Je pensais qu'il était complet mais je n'ai jamais entendu dire s'il répondait aux attentes de l'équipe de projet. Je ne l'ai pas regardé depuis, et je ne sais pas ce que les gens veulent en faire.

J'ai un temps très limité sur plusieurs projets. Ne vous inquiétez pas, ne l'avez pas oublié.

@davidism Merci, pas seulement d'avoir répondu mais d'avoir fait le bon travail pour maintenir ces projets en vie !

Bien que cela ne soit toujours pas fusionné, une solution temporaire possible consiste à patcher la fonction _get_args_for_reloading() quelque part avant qu'elle ne soit utilisée. Dans le cas d'un script Flask, l'ajouter quelque part au début d'un fichier manage.py aide :

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
Cette page vous a été utile?
0 / 5 - 0 notes