Werkzeug: Scripts de consola de Windows llamados desde el recargador

Creado en 13 jun. 2017  ·  14Comentarios  ·  Fuente: pallets/werkzeug

Estoy ejecutando apistar en python 3 y encuentro un problema que me ha llevado al cargador 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

Eliminar el use_reloader de la llamada a run_simple() funciona. Después de profundizar en un par de comentarios, descubrí que https://github.com/pallets/werkzeug/blob/master/werkzeug/_reloader.py#L118 está codificando algo para latin1 pero solo cuando el sistema operativo es Windows y la versión de Python es 2. ¿Podría esto estar causando el error de sintaxis no UTF-8 que estoy recibiendo en python3?

Todos 14 comentarios

¿Hay un pequeño ejemplo que pueda usar para reproducir esto? No estoy familiarizado con el uso de apistar y no uso Windows con regularidad.

Lo investigué un poco más. El problema es en realidad con _get_args_for_reloading () . Ese método devuelve argumentos que son ['python.exe', 'apistar.exe', 'run'] que cuando se pasan a subprocess.call() generan ese error. No es diferente a llamar a python.exe apistar.exe run desde la línea de comando.

Entonces, el problema no es con la codificación del entorno como pensé originalmente. Dado que sería una ocurrencia muy común en otros marcos basados ​​en werkzueg, creo que un cambio en este método para tener en cuenta el hecho de que podría ser llamado a través de un .exe generado por console_script beneficiaría a todos los usuarios de Windows.

Estoy cambiando el título del problema para dar cuenta de esto.

Si este método eliminó el elemento sys.executable de rv dentro de la comprobación de Windows, la recarga se realizó correctamente:

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

Me complace revisar un PR si desea enviar uno.

Definitivamente me gustaría, pero estoy un poco atascado escribiendo una prueba para esto. Solo puedo ver que esto funciona con la biblioteca unittest.mock y parcheando sys.executable y os.name, pero supongo que esto no funcionaría para su proyecto, ya que también tiene que admitir pruebas automatizadas en 27. ¿Algún consejo?

Además, ¿cuál es la estrategia de ramificación utilizada aquí? ¿Las solicitudes de extracción para problemas van en contra de la rama de mantenimiento actual?

Puede pasar de 0.12-mantenimiento. Primero veamos cómo se ve un parche y luego descubramos la prueba.

Envié una solicitud de extracción. Sin embargo, parece que el Travis CI está fallando por razones no relacionadas con los cambios que hice. Esta es mi primera solicitud de extracción, así que no sé a dónde ir desde aquí.

Esto sucederá cuando tenga instalados los lanzadores exe de setuptools. Si lo instala a través de un pip actualizado, se instala un nuevo tipo de lanzadores exe (de distlib ) que runpy docs ).

Esto no significa que no deba solucionarse, pero es útil saberlo en caso de que no pueda reproducirlo. Todavía sucederá si instala Flask en modo de desarrollo ( pip install -e ) por ejemplo.

@androiddrew @davidism ¿ alguna actualización sobre este PR?

@segevfiner, ¿puedes agregar un poco más de detalle a tu comentario más reciente? ¿Está sugiriendo que probablemente deberíamos arreglar la causa raíz en setuptools en lugar de en Flask?

@ewpete La causa principal es que cuando se utilizan lanzadores generados por setuptools,
el sys.argv [0] no es ejecutable como un script de Python ya que es el
lanzador exe. La secuencia de comandos real se denomina como el exe con - "-script"
adjunta y el exe lo carga y lo ejecuta.

Tenga en cuenta que el exe se puede ejecutar directamente (y también lo es un script de Python
con shebang, que creo que es lo que setuptools genera en unices). Pero
hacerlo para scripts simples de Python en Windows no es confiable (cuando el
pylauncher no está instalado), ya que se iniciará con el Python arbitrario
que está asociado para los archivos .py en el registro, que pueden ser diferentes
que el Python actual que estamos usando. Y, por supuesto, lo mismo se aplica a
cualquier script de Python aleatorio desde el que podamos ser invocados, que ni siquiera puede ser
ejecutable.

pip instala en su lugar (a través de distlib) un nuevo tipo de lanzador exe que tiene la
secuencia de comandos de inicio generada adjunta dentro de un zip al final de la
ejecutable. Esto se detectará como un archivo zip con un script __main__.py (A
zipapp) y se puede pasar directamente a Python para su ejecución.

Arreglar esto en setuptools significará generar un tipo similar / mismo tipo
lanzadores en setuptools. Y en el espíritu de http://xkcd.com/1172/ , este
probablemente romperá el código que espera que los lanzadores de setuptools e intente
utilizando los archivos "* -script.py" para solucionar el problema. Yo no comprobé
si ya hay un problema / pr sobre esto.

Probablemente esté bien tener una pequeña solución aquí para que Werkzeug
El recargador funciona incluso en presencia del estilo actual de las herramientas de configuración.
lanzadores. Pero eso depende realmente de los responsables del proyecto.

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

@androiddrew https://github.com/androiddrew @davidism
https://github.com/davidism ¿ alguna actualización sobre este PR?

@segevfiner https://github.com/segevfiner ¿puedes agregar un poco más?
detalle a su comentario más reciente? ¿Estás sugiriendo que deberíamos
probablemente solucione la causa raíz en setuptools en lugar de en Flask?

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/pallets/werkzeug/issues/1136#issuecomment-347623921 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AXlg_8OSR3NdbPJzM87dyKPUAA9NpXJ6ks5s7FT7gaJpZM4N5Fcb
.el

@ewpete Este fue mi primer PR. Hice todo lo posible para escribir pruebas, seguir la guía de desarrollo y colocar el PR. No tenía mucha orientación sobre cómo hacer esto, pero hice los cambios sugeridos a partir de los comentarios de relaciones públicas. Pensé que estaba completo, pero nunca supe si cumplía con las expectativas del equipo del proyecto. No lo he mirado desde entonces y no sé qué quiere hacer la gente con él.

Tengo un tiempo muy limitado en varios proyectos. No se preocupe, no se ha olvidado de esto.

@davidism ¡ Gracias, no solo por responder sino por hacer el buen trabajo de mantener vivos estos proyectos!

Si bien esto aún no está combinado, una posible solución temporal es parchear la función _get_args_for_reloading() algún lugar antes de que se use. En el caso de un script de Flask, agregar esto en algún lugar al comienzo de un archivo manage.py ayuda:

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
¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

miki725 picture miki725  ·  10Comentarios

golf-player picture golf-player  ·  10Comentarios

caiz picture caiz  ·  3Comentarios

KangOl picture KangOl  ·  16Comentarios

d42 picture d42  ·  6Comentarios