Werkzeug: Reloader, python -m et sys.path

Créé le 11 nov. 2013  ·  12Commentaires  ·  Source: pallets/werkzeug

Voir https://github.com/Kozea/WeasyPrint/issues/133

Ce qui se passe, c'est:

  • python -m weasyprint.navigator est exécuté
  • [sys.executable] + sys.argv est ['…/python', '…/weasyprint/navigator.py']
  • Le rechargeur génère un sous-processus de cette façon
  • Le processus enfant n'a pas -m , donc Python ajoute le répertoire parent du fichier .py à sys.path
  • Werkzeug essaie d'importer les html.entities stdlib
  • Cela importe par erreur weasyprint/html.py
  • Pauses trucs

Personne ici ne fait manifestement rien de mal. Comment proposez-vous de gérer cette situation? Que pensez-vous du fait que …/weasyprint/navigator.py (qui devrait être principalement utilisé avec python -m ) supprime son répertoire parent de sys.path s'il y est?

bug reloader

Commentaire le plus utile

J'ai un problème similaire, où les importations relatives échouent car le rechargeur exécute le module en tant que non-package:

$ python -m myapp.entrypoints.website
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
Traceback (most recent call last):
  File "/tmp/myapp/entrypoints/website.py", line 9, in <module>
    from . import mymodule
ValueError: Attempted relative import in non-package

En utilisant les commentaires de @untitaker , en Python <3.3, nous pouvons détecter si python -m été utilisé (alors seulement __loader__ défini) et forcer le rechargeur à l'utiliser également en réinitialisant sys.argv :

try:
    sys.argv = ['-m', __loader__.fullname] + sys.argv[1:]
except NameError:
    pass

Mais c'est une solution de contournement assez piratée (et uniquement pour Python <3.3).

L'implémentation actuelle dans # 531 ne résout pas ce problème particulier et je ne vois malheureusement pas comment cela pourrait.

Tous les 12 commentaires

Je ne pense pas que cela ne ferait pas de mal si Werkzeug engendrait le sous-processus avec en fait les mêmes arguments, en utilisant __loader__.fullname en Python 2 et __loader__.name en Python 3 s'il existe.

@untitaker , je ne comprends pas ce que vous voulez dire. Qu'est-ce que __loader__ ?

Peut-on détecter en Python si python -m somemodule été utilisé ou non?

Je suis tombé sur une réponse StackOverflow qui expliquait comment obtenir le nom du module actuel. Un test simple montre qu'en Python 2, __loader__.fullname est disponible:

print(__loader__.fullname)

Le __loader__ global n'existe pas si le fichier Python est exécuté sans -m , et il n'existe pas non plus dans les modules importés.

Dans Python 3, le module exécuté avec -m et tous les autres modules importés semblent avoir un __loader__ global, l'attribut fullname est maintenant name . Mais à l'intérieur de chaque module, l'attribut name a la valeur du module _current_.

Ainsi, dans Python 2, nous _pouvons_ détecter si nous fonctionnons avec -m , mais pas avec 3.

De plus, la détection est très limitée non plus, donc vous ne pouvez détecter à l'intérieur du module exécuté directement que si python -m été utilisé en vérifiant la variable __loader__ . De plus, ce comportement semble peu documenté, donc je ne suis pas sûr que ce soit ce que nous voulons de toute façon dans Werkzeug.

Je viens de tomber sur ce bug moi-même. Je m'attendais à ce que le drapeau -m soit présent dans sys.argv , mais ce n'est certainement pas le cas.

Existe-t-il une solution de contournement pour cela?

Oui, un est présenté sur https://github.com/mitsuhiko/flask/issues/1246

Le 9 juillet 2015 à 15:08:30 CEST, Wayne Werner [email protected] a écrit:

Je viens de tomber sur ce bug moi-même. Je m'attendais à ce que l'indicateur -m soit
présent dans sys.argv , mais ce n'est certainement pas le cas.

Existe-t-il une solution de contournement pour cela?


Répondez directement à cet e-mail ou affichez-le sur GitHub:
https://github.com/mitsuhiko/werkzeug/issues/461#issuecomment -119955695

Envoyé depuis mon appareil Android avec K-9 Mail. Veuillez excuser ma brièveté.

J'ai un problème similaire, où les importations relatives échouent car le rechargeur exécute le module en tant que non-package:

$ python -m myapp.entrypoints.website
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
Traceback (most recent call last):
  File "/tmp/myapp/entrypoints/website.py", line 9, in <module>
    from . import mymodule
ValueError: Attempted relative import in non-package

En utilisant les commentaires de @untitaker , en Python <3.3, nous pouvons détecter si python -m été utilisé (alors seulement __loader__ défini) et forcer le rechargeur à l'utiliser également en réinitialisant sys.argv :

try:
    sys.argv = ['-m', __loader__.fullname] + sys.argv[1:]
except NameError:
    pass

Mais c'est une solution de contournement assez piratée (et uniquement pour Python <3.3).

L'implémentation actuelle dans # 531 ne résout pas ce problème particulier et je ne vois malheureusement pas comment cela pourrait.

Je pense que j'ai essayé de résoudre ce problème avec le chargeur une fois, mais cela a montré énormément
comportement différent de 2 à 3.

Le jeu.10 septembre 2015 à 13:26:56 -0700, Martijn Vermaat a écrit:

J'ai un problème similaire, où les importations relatives échouent car le rechargeur exécute le module en tant que non-package:

$ python -m myapp.entrypoints.website
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
Traceback (most recent call last):
  File "/tmp/myapp/entrypoints/website.py", line 9, in <module>
    from . import mymodule
ValueError: Attempted relative import in non-package

En utilisant les commentaires de @untitaker , en Python <3.3, nous pouvons détecter si python -m été utilisé (alors seulement __loader__ défini) et forcer le rechargeur à l'utiliser également en réinitialisant sys.argv :

try:
    sys.argv = ['-m', __loader__.fullname] + sys.argv[1:]
except NameError:
    pass

Mais c'est une solution de contournement assez piratée (et uniquement pour Python <3.3).


Répondez directement à cet e-mail ou affichez-le sur GitHub:
https://github.com/mitsuhiko/werkzeug/issues/461#issuecomment -139369694

Malheureusement,

$ python -m werkzeug.serving weasyprint. navigateur: app --reload --debug

  • Exécution sur http://127.0.0.1 : 5000 / (Appuyez sur CTRL + C pour quitter)
  • Redémarrer avec stat
    Traceback (dernier appel le plus récent):
    Fichier "/usr/lib/python2.7/site-packages/werkzeug/serving.py", ligne 45, dans
    depuis ._compat import PY2
    ValueError: tentative d'importation relative dans un non-package

Ce bogue de python ne peut pas être corrigé correctement avec python, je suggère donc de fournir un script de console

Y a-t-il un changement à cela? Je viens de rencontrer ce problème ... (Python 3.6, pas de weasyprint, juste python -m werkzeug.serving app:application )

J'ai réussi à contourner le problème en faisant quelque chose comme:

PYTHONPATH=$PWD:$PYTHONPATH python -m myapp.entrypoints.website

_Edit: réalisé que la solution était juste au-dessus : arrow_up: _

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

ngaya-ll picture ngaya-ll  ·  8Commentaires

c17r picture c17r  ·  4Commentaires

androiddrew picture androiddrew  ·  14Commentaires

davidism picture davidism  ·  9Commentaires

golf-player picture golf-player  ·  10Commentaires