Flask CLI 在通过 docker-compose 运行时抛出“OSError: [Errno 8] Exec 格式错误" [英] Flask CLI throws 'OSError: [Errno 8] Exec format error' when run through docker-compose

查看:69
本文介绍了Flask CLI 在通过 docker-compose 运行时抛出“OSError: [Errno 8] Exec 格式错误"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行带有 自定义脚本的 Flask 应用程序.或者尝试,无论如何.

我使用的是 Windows 10,应用程序应该使用以下命令在 linux Docker 容器中运行:

docker-compose up api

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

命令:python manage.py run --host "0.0.0.0" --with-threads

当它尝试启动时,我看到异常

OSError: [Errno 8] Exec 格式错误: '/api/manage.py'

我最初认为这将是可怕的 Windows 行尾,再次来找我,但是在我的所有源文件上运行 dos2unix 并没有解决问题.

我怎样才能避免这个错误?

<小时>

ma​​nage.py

 导入点击从flask.cli 导入FlaskGroup从 my_app_api 导入 create_appdef create_my_app(info):返回 create_app()@click.group(cls=FlaskGroup, create_app=create_my_app)定义 cli():经过如果 __name__ == "__main__":cli()

完整追溯

api_1 |回溯(最近一次调用最后一次):api_1 | 中的文件manage.py",第 22 行api_1 |cli()api_1 |文件/usr/local/lib/python3.6/site-packages/click/core.py",第 764 行,在 __call__ 中api_1 |返回 self.main(*args, **kwargs)api_1 |文件/usr/local/lib/python3.6/site-packages/flask/cli.py",第380行,在主目录中api_1 |返回 AppGroup.main(self, *args, **kwargs)api_1 |文件/usr/local/lib/python3.6/site-packages/click/core.py",第 717 行,在 mainapi_1 |rv = self.invoke(ctx)api_1 |调用中的文件/usr/local/lib/python3.6/site-packages/click/core.py",第 1137 行api_1 |返回_process_result(sub_ctx.command.invoke(sub_ctx))api_1 |调用中的文件/usr/local/lib/python3.6/site-packages/click/core.py",第 956 行api_1 |返回 ctx.invoke(self.callback, **ctx.params)api_1 |调用中的文件/usr/local/lib/python3.6/site-packages/click/core.py",第 555 行api_1 |返回回调(*args,**kwargs)api_1 |文件/usr/local/lib/python3.6/site-packages/click/decorators.py",第64行,在new_funcapi_1 |返回 ctx.invoke(f, obj, *args, **kwargs)api_1 |调用中的文件/usr/local/lib/python3.6/site-packages/click/core.py",第 555 行api_1 |返回回调(*args,**kwargs)api_1 |run_command 中的文件/usr/local/lib/python3.6/site-packages/flask/cli.py",第 438 行api_1 |use_debugger=调试器,threaded=with_threads)api_1 |文件/usr/local/lib/python3.6/site-packages/werkzeug/serving.py",第 988 行,在 run_simple 中api_1 |run_with_reloader(内部,extra_files,reloader_interval,reloader_type)api_1 |文件/usr/local/lib/python3.6/site-packages/werkzeug/_reloader.py",第332行,在run_with_reloaderapi_1 |sys.exit(reloader.restart_with_reloader())api_1 |文件/usr/local/lib/python3.6/site-packages/werkzeug/_reloader.py",第176行,在restart_with_reloaderapi_1 |exit_code = subprocess.call(args, env=new_environ, close_fds=False)api_1 |文件/usr/local/lib/python3.6/subprocess.py",第 287 行,调用中api_1 |使用 Popen(*popenargs, **kwargs) 作为 p:api_1 |文件/usr/local/lib/python3.6/subprocess.py",第 729 行,在 __init__ 中api_1 |restore_signals,start_new_session)api_1 |文件/usr/local/lib/python3.6/subprocess.py",第 1364 行,在 _execute_childapi_1 |引发 child_exception_type(errno_num, err_msg, err_filename)api_1 |OSError: [Errno 8] Exec 格式错误: '/api/manage.py'

解决方案

看起来你的 api/manage.py 没有 shebang ([维基百科]: Shebang (Unix)),所以默认 (当前)命令处理器(shell - 通常是 bash)正在尝试运行它,这(显然)失败了.

要更正问题,请添加 shebang(在文件开头,确保您的编辑器添加了 Nix 样式的行尾( 0x0ALF)):

  • 默认 Python 安装:

     #!/usr/bin/env python

    • 变体(明确指定Python 3):

       #!/usr/bin/env python3

  • 自定义Python安装:

     #!/full/path/to/your/custom/python/executable

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

示例:

<块引用>

[cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q055271912]>〜/sopr.sh*** 当粘贴到 StackOverflow(或其他)页面时,设置更短的提示以更好地适应 ***[提示]>ls代码00.py 代码01.py[提示]>[提示]>猫代码00.py打印(这是:",__file__)[提示]>python3 -c "import os, subprocess;subprocess.Popen(os.path.join(os.getcwd(), "code00.py")).communicate()";回溯(最近一次调用最后一次):文件<string>",第 1 行,在 <module> 中.文件/usr/lib/python3.6/subprocess.py",第 709 行,在 __init__ 中restore_signals,start_new_session)文件/usr/lib/python3.6/subprocess.py",第 1344 行,在 _execute_child 中引发 child_exception_type(errno_num, err_msg, err_filename)OSError: [Errno 8] Exec 格式错误: '/cygdrive/e/Work/Dev/StackOverflow/q055271912/code00.py'[提示]>[提示]>猫代码01.py#!/usr/bin/env python3打印(这是:",__file__)[提示]>python3 -c "import os, subprocess;subprocess.Popen(os.path.join(os.getcwd(), "code01.py")).communicate()";这是:/cygdrive/e/Work/Dev/StackOverflow/q055271912/code01.py

另一种方法是运行后跟文件名的解释器,但我不知道如何从 Flask 执行此操作 - 实际上这需要修补 Werkzeug(_reloader.py: _get_args_for_reloading),但这只是一个蹩脚的解决方法 (gainarie) - 见下文.



更新#0

查看@AxelGrytt 的回答,发现这是一个已知问题:[GitHub]:托盘/werkzeug - 0.15.0 导致 OSError: [Errno 8] Exec format error: in Docker for Windows(嗯,与这个问题在同一天提交(和发布后 2 天):)).>

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

chmod -x api/manage.py

根据 Werkzeug 作者的说法,从现在开始,这是理想的行为(也适用于 v0.15.2em>):

  • 一个具有exec权限集的文件,应该也有一个shebang
  • 一个没有shebang的文件,不应该具有exec权限集

I'm running a Flask application with a Custom Script. Or trying to, anyway.

I'm on Windows 10 and the application ought to run in a linux Docker container with the command:

docker-compose up api

Docker-compose is version 1.23.2. In the dockerfile, the api service runs via the command:

command: python manage.py run --host "0.0.0.0" --with-threads

As it tries to start up, I see the exception

OSError: [Errno 8] Exec format error: '/api/manage.py'

I initially thought this would be the Dreaded Windows Line Endings, come for me once more, but running dos2unix on all my source files has not resolved the problem.

How can I avoid this 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()

Full traceback

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'

解决方案

Looks like your api/manage.py doesn't have a shebang ([Wikipedia]: Shebang (Unix)), so the default (current) command processor (a shell - typically bash) is attempting to run it, which (obviously) fails.

To correct the problem, add a shebang (at the beginning of the file, making sure that your editor adds the Nix style line ending ( , 0x0A, LF)):

  • Default Python installation:

      #!/usr/bin/env python
    

    • Variant (specify Python 3 explicitly):

        #!/usr/bin/env python3
      

  • Custom Python installation:

      #!/full/path/to/your/custom/python/executable
    

Note that you also need exec permissions on the file (chmod +x api/manage.py).

Example:

[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
code00.py  code01.py
[prompt]>
[prompt]> cat code00.py
print("This is:", __file__)

[prompt]> python3 -c "import os, subprocess;subprocess.Popen(os.path.join(os.getcwd(), "code00.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/code00.py'
[prompt]>
[prompt]> cat code01.py
#!/usr/bin/env python3

print("This is:", __file__)

[prompt]> python3 -c "import os, subprocess;subprocess.Popen(os.path.join(os.getcwd(), "code01.py")).communicate()"
This is: /cygdrive/e/Work/Dev/StackOverflow/q055271912/code01.py

Another way would be to run the interpreter followed by the file name, but I don't know how to do it from Flask - actually that would require patching Werkzeug (_reloader.py: _get_args_for_reloading), but that would be just a lame workaround (gainarie) - see below.



Update #0

Looking at @AxelGrytt's answer, it turns out it's a known issue: [GitHub]: pallets/werkzeug - 0.15.0 causes OSError: [Errno 8] Exec format error: in Docker for Windows (hmm, submitted in the same day as this question (and 2 days after the release) :) ).

So, what I have stated above is correct, but it is worth mentioning that there is another way of fixing it: removing the exec permission for the file:

chmod -x api/manage.py

According to Werkzeug authors, from now on, this is desired behavior (also applies to v0.15.2):

  • A file with exec permission set, should also have a shebang
  • A file without a shebang, shouldn't have the exec permission set

这篇关于Flask CLI 在通过 docker-compose 运行时抛出“OSError: [Errno 8] Exec 格式错误"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆