That was definitely the right clue, but I’m still stuck on an incomplete model of flask and servers. Here’s the hole I dig (omitting host addresses and imports et al):
1. python index.py
This worked fine in development.
app.py
import dash
app = dash.Dash(__name__, suppress_callback_exceptions=True)
server = app.server
index.py
…
from app import app
…
if __name__ == '__main__':
app.run_server()
2. gunicorn index:server
Same files as above. First attempt to move to production, got Error:
Failed to find attribute 'server' in 'index'.
3. gunicorn index:server v2
Removed app.py and changed index.py to include
…
app = Dash(__name__)
server = app.server
…
if __name__ == '__main__':
app.run_server()
This starts fine, but produces a website where only the callbacks in index.py work, not any of the callbacks defined in other files.
4. python index.py v2
When I followed your advice backwards and ran python instead of gunicorn, I found that this version of the code was broken the same way (no working callbacks from other files), even with the debug server.
So where I’m stuck is, what pattern of code both loads all of the callbacks correctly and can be run by both python and gunicorn? The code on Multi-page Apps points toward putting all callbacks in index.py, as with this forum post, but this loses most of the advantages of splitting code in different pages.