python - Flask CLI lanza ''OSError:[Errno 8] Error de formato de ejecución'' cuando se ejecuta a través de docker-compose
windows (4)
Este es un nuevo comportamiento en Werkzeug 0.15. La reducción a Werkzeug 0.14.1 puede funcionar, pero 0.14 ya no es compatible, por lo que será mejor que corrija el problema con su archivo como se describe en las otras respuestas.
Estoy ejecutando una aplicación Flask con un script personalizado . O intentarlo, de todos modos.
Estoy en Windows 10 y la aplicación debería ejecutarse en un contenedor Docker de Linux con el comando:
docker-compose up api
Docker-compose es la
version 1.23.2
.
En el archivo docker, el servicio
api
ejecuta a través del comando:
command: python manage.py run --host "0.0.0.0" --with-threads
Mientras trata de arrancar, veo la excepción.
OSError: [Errno 8] Exec format error: ''/api/manage.py''
Inicialmente pensé que estos serían los Finales de Línea Dreaded de Windows, venga por mí una vez más, pero ejecutar
dos2unix
en todos mis archivos de origen no ha resuelto el problema.
¿Cómo puedo evitar este error?
manage.py
import click
from flask.cli import FlaskGroup
from my_app_api import create_app
def create_my_app(info):
return create_app()
@click.group(cls=FlaskGroup, create_app=create_my_app)
def cli():
pass
if __name__ == "__main__":
cli()
Traceback completo
api_1 | Traceback (most recent call last):
api_1 | File "manage.py", line 22, in <module>
api_1 | cli()
api_1 | File "/usr/local/lib/python3.6/site-packages/click/core.py", line 764, in __call__
api_1 | return self.main(*args, **kwargs)
api_1 | File "/usr/local/lib/python3.6/site-packages/flask/cli.py", line 380, in main
api_1 | return AppGroup.main(self, *args, **kwargs)
api_1 | File "/usr/local/lib/python3.6/site-packages/click/core.py", line 717, in main
api_1 | rv = self.invoke(ctx)
api_1 | File "/usr/local/lib/python3.6/site-packages/click/core.py", line 1137, in invoke
api_1 | return _process_result(sub_ctx.command.invoke(sub_ctx))
api_1 | File "/usr/local/lib/python3.6/site-packages/click/core.py", line 956, in invoke
api_1 | return ctx.invoke(self.callback, **ctx.params)
api_1 | File "/usr/local/lib/python3.6/site-packages/click/core.py", line 555, in invoke
api_1 | return callback(*args, **kwargs)
api_1 | File "/usr/local/lib/python3.6/site-packages/click/decorators.py", line 64, in new_func
api_1 | return ctx.invoke(f, obj, *args, **kwargs)
api_1 | File "/usr/local/lib/python3.6/site-packages/click/core.py", line 555, in invoke
api_1 | return callback(*args, **kwargs)
api_1 | File "/usr/local/lib/python3.6/site-packages/flask/cli.py", line 438, in run_command
api_1 | use_debugger=debugger, threaded=with_threads)
api_1 | File "/usr/local/lib/python3.6/site-packages/werkzeug/serving.py", line 988, in run_simple
api_1 | run_with_reloader(inner, extra_files, reloader_interval, reloader_type)
api_1 | File "/usr/local/lib/python3.6/site-packages/werkzeug/_reloader.py", line 332, in run_with_reloader
api_1 | sys.exit(reloader.restart_with_reloader())
api_1 | File "/usr/local/lib/python3.6/site-packages/werkzeug/_reloader.py", line 176, in restart_with_reloader
api_1 | exit_code = subprocess.call(args, env=new_environ, close_fds=False)
api_1 | File "/usr/local/lib/python3.6/subprocess.py", line 287, in call
api_1 | with Popen(*popenargs, **kwargs) as p:
api_1 | File "/usr/local/lib/python3.6/subprocess.py", line 729, in __init__
api_1 | restore_signals, start_new_session)
api_1 | File "/usr/local/lib/python3.6/subprocess.py", line 1364, in _execute_child
api_1 | raise child_exception_type(errno_num, err_msg, err_filename)
api_1 | OSError: [Errno 8] Exec format error: ''/api/manage.py''
La respuesta de @CristiFati me funcionó con 1 paso adicional:
También tuve que corregir el EOL de
/r/n
a
/n
.
Lo siento, no tengo suficientes puntos para agregar un comentario y tengo que abrir una nueva respuesta ...
Parece que su api / manage.py no tiene un shebang ( [Wikipedia]: Shebang (Unix) ), por lo que el procesador de comandos predeterminado (actual) (un shell - normalmente bash ) está intentando ejecutarlo, lo que (obviamente) falla
Para corregir el problema, agregue un shebang (al principio del archivo, asegurándose de que su editor agregue el final de la línea de estilo Nix ( / n , 0x0A , LF )):
-
Instalación predeterminada de Python :
#!/usr/bin/env python
-
Variante (especifique Python 3 explícitamente):
#!/usr/bin/env python3
-
-
Instalación personalizada de Python :
#!/full/path/to/your/custom/python/executable
Tenga en cuenta que también necesita permisos de
ejecución
en el archivo (
chmod +x api/manage.py
).
Ejemplo:
[cfati@cfati-5510-0:/cygdrive/e/Work/Dev//q055271912]> ~/sopr.sh *** Set shorter prompt to better fit when pasted in (or other) pages *** [prompt]> ls code0.py code1.py [prompt]> [prompt]> cat code0.py print("This is:", __file__) [prompt]> python3 -c "import os, subprocess;subprocess.Popen(os.path.join(os.getcwd(), /"code0.py/")).communicate()" Traceback (most recent call last): File "<string>", line 1, in <module> File "/usr/lib/python3.6/subprocess.py", line 709, in __init__ restore_signals, start_new_session) File "/usr/lib/python3.6/subprocess.py", line 1344, in _execute_child raise child_exception_type(errno_num, err_msg, err_filename) OSError: [Errno 8] Exec format error: ''/cygdrive/e/Work/Dev//q055271912/code0.py'' [prompt]> [prompt]> cat code1.py #!/usr/bin/env python3 print("This is:", __file__) [prompt]> python3 -c "import os, subprocess;subprocess.Popen(os.path.join(os.getcwd(), /"code1.py/")).communicate()" This is: /cygdrive/e/Work/Dev//q055271912/code1.py
Otra forma sería ejecutar el intérprete seguido del nombre del archivo, pero no sé cómo hacerlo desde Flask ; en realidad, eso requeriría parchear Werkzeug ( _reloader.py : _get_args_for_reloading ), pero eso sería solo una solución poco convincente ( gainarie ) - ver más abajo.
@ EDIT0 :
Mirando la respuesta de @ AxelGrytt, resulta que es un problema conocido: [GitHub]: pallets / werkzeug - 0.15.0 hace que OSError: [Errno 8] Error de formato Exec: en Docker para Windows (hmm, enviado el mismo día que este Pregunta (y 2 días después del lanzamiento) :)).
Entonces, lo que he dicho anteriormente es correcto, pero vale la pena mencionar que hay otra forma de solucionarlo: eliminar el permiso exec para el archivo:
chmod -x api/manage.py
Según los autores de Werkzeug , a partir de ahora, este es el comportamiento deseado (también se aplica a v 0.15.2 ):
- Un archivo con el permiso exec establecido, también debe tener un shebang
- Un archivo sin un shebang , no debería tener el permiso exec establecido
Si deshabilita el modo de depuración (no pase
debug=True
o configure
FLASK_DEBUG=0
), el reloader no se utilizará y, por lo tanto, este problema no se producirá.
La compensación es que ya no tienes el recargador.
if __name__ == "__main__":
connexion_app.run(host="0.0.0.0", port=constants.API_PORT, debug=True)
Es preferible solucionar esto asegurando que los archivos marcados como ejecutables tengan una línea de intérprete, como
#!/usr/bin/env python3
(de
share
).