在通过docker-compose运行时,Flask CLI抛出“ OSError:[Errno 8] Exec格式错误”

ale*_*ian 27 python windows flask docker docker-compose

我正在使用自定义脚本运行Flask应用程序。还是尝试,无论如何。

我在Windows 10上,应用程序应在Linux Docker容器中使用以下命令运行:

docker-compose up api
Run Code Online (Sandbox Code Playgroud)

Docker-compose是version 1.23.2。在dockerfile中,该api服务通过以下命令运行:

command: python manage.py run --host "0.0.0.0" --with-threads
Run Code Online (Sandbox Code Playgroud)

在尝试启动时,我看到了异常

OSError: [Errno 8] Exec format error: '/api/manage.py'
Run Code Online (Sandbox Code Playgroud)

我最初以为这将是“可怕的Windows行尾”,再次给我,但是dos2unix在我的所有源文件上运行都无法解决问题。

如何避免此错误?


manage.py

docker-compose up api
Run Code Online (Sandbox Code Playgroud)

完整回溯

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'
Run Code Online (Sandbox Code Playgroud)

Cri*_*ati 44

看起来您的api / manage.py没有shebang[Wikipedia]:Shebang(Unix)),因此默认(当前)命令处理器(shell-通常为bash)正在尝试运行它,(显然)失败。

要解决此问题,请添加一个shebang(在文件的开头,确保您的编辑器添加了结尾为Nix样式的行(\ n0x0ALF)):

请注意,您还需要对该文件()具有执行权限chmod +x api/manage.py

例:

[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q055271912]> ~/sopr.sh
*** Set shorter prompt to better fit when pasted in StackOverflow (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/StackOverflow/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/StackOverflow/q055271912/code1.py
Run Code Online (Sandbox Code Playgroud)


另一种方法是运行解释后面的文件名,但我不知道如何从做 -实际上是需要修补WERKZEUG_reloader.py_get_args_for_reloading),但这只是一个蹩脚的解决方法(gainarie)-见下文。

@ EDIT0

查看@AxelGrytt的答案,结果发现这是一个已知问题:[GitHub]:pallets / werkzeug-0.15.0导致OSError:[Errno 8] Exec格式错误:在Docker for Windows中(hmm,与此同时提交问题(发布后2天):))。

因此,我上面所说的是正确的,但是值得一提的是,还有另一种修复方法:删除文件的exec权限:

chmod -x api/manage.py
Run Code Online (Sandbox Code Playgroud)

根据Werkzeug的作者,从现在开始,这是理想的行为(也适用于v 0.15.2):

  • 设置 exec权限的文件,还应该有一个shebang
  • 一个文件没有一个家当不应该EXEC权限集


小智 28

这是Werkzeug 0.15中的新行为。降级到Werkzeug 0.14.1可能有效,但是不再支持0.14,因此最好按照其他答案中所述纠正文件问题。


Yan*_*ski 8

如果禁用调试模式(不通过debug=True或设置FLASK_DEBUG=0),则不会使用重新加载器,因此不会发生此问题。折衷是您不再需要重新加载器。

if __name__ == "__main__":
    connexion_app.run(host="0.0.0.0", port=constants.API_PORT, debug=True)
Run Code Online (Sandbox Code Playgroud)

最好通过确保标记为可执行文件的文件具有解释器行来解决此问题,例如#!/usr/bin/env python3(from /sf/answers/3869045001/)。