简体   繁体   中英

Gunicorn 20 failed to find application object 'app.server' in 'index'

I'm using Gunicorn to deploy my Dash app. After upgrading to Gunicorn 20.0.0, it fails to find my application.

gunicorn --bind=0.0.0.0 --timeout 600 index:app.server
Failed to find application object 'app.server' in 'index'
[INFO] Shutting down: Master
[INFO] Reason: App failed to load.

This issue on Gunicorn's issue tracker seems to be related to the error, but I can't figure out what I'm supposed to do to fix it. How can I make Gunicorn 20 find my app?

index.py :

import os
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
from pages import overview
from webapp import app

app.index_string = open(os.path.join("html", "index.html")).read()
app.layout = html.Div([
    dcc.Location(id="url", refresh=False),
    html.Div(id="page-content")
])

@app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def display_page(pathname):
    if pathname == "/a-service/overview":
        return overview.layout
    else:
        return overview.layout

if __name__ == "__main__":
    app.run_server(debug=True, port=8051)

webapp.py :

import dash

description = "a description"
title = "a title"
creator = "@altf1be"
app = dash.Dash(
    __name__,
    meta_tags=[
        {"name": "viewport", "content": "width=device-width, initial-scale=1"},
        {"name": "description", "content": description},
        {"name": "twitter:description", "content": description},
        {"property": "og:title", "content": description},
        {"name": "twitter:creator", "content": creator}
    ]
)
server = app.server
app.config.suppress_callback_exceptions = True

Gunicorn 20 changed how it parses and loads the application argument. It used to use eval , which followed attribute access. Now it only does a simple lookup for a single name in the given module. The ability for Gunicorn to understand Python syntax such as attribute access was not documented or intended.

Dash's docs about deployment don't use the syntax you're using though. They say to do the following, which will work for any version of Gunicorn:

webapp.py :

server = app.server
$ gunicorn webapp:server

You're already adding the server alias in the webapp module, but your code layout is a bit off and making things confusing for you. You're ignoring the setup you do in webapp and using index as your entry point instead. You're putting everything in separate top-level modules rather than within a package.

If you want to split your app setup from your index views, you should follow the standard Flask pattern of defining the app, then importing the views after that, all within a package.

project/
  myapp/
    __init__.py
    webapp.py
    index.py

webapp.py :

app = dash.Dash(...)
server = app.server

# index imports app, so import it after app is defined to avoid a circular import
from myapp import index
$ gunicorn myapp.webapp:server

you should also import server from webapp.py to index.py and then use regular gunicorn procedure:

gunicorn index:server -b :8000

A Dash project that is structured as a multi-page app ( https://dash.plotly.com/urls ) will have app.py (named as webapp.py here) and index.py . As mentioned in the linked guide, the entry point should be index.py to prevent circular import.

Only two changes are needed to use index.py as the entry point:

  1. Import both app and server into index.py

from webapp import app, server

  1. Run gunicorn as follows

gunicorn -b localhost:8000 index:server

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM