Following the guidance Multi-Page Apps and URL Support to create a multi-page app, however,
I do not see a reasonable way to access the app object in callbacks defined on individual pages stored in the folder pages/.
I have tried to import it from the parent folder with
If @chriddyp , @nedned , or anyone else here uses Flask’s logger in multi-page apps I would be extremely grateful for a note on an approach to making this work that you could recommend?
Another way to get access to the Flask server instance of your Dash app that means you don’t have to thread app imports all throughout your modules is Flask’s current_app: The Application Context — Flask Documentation (2.3.x). The only limitation is that you can only access flask.current_app from inside an application context, which, practically, I think amounts to making sure you only access it inside a callback.
I have installed version: 2.7.0 of the dash package and use a Windows 10 box.
I have no __init__.py in my app’s root folder, the folder pages/ should be the only package in this setup, rf. item 3.
app.py has the contents
import dash, dash_bootstrap_components
import logging # Do I still need this when using app.logger instead of creating my own logger?
logging.config.fileConfig('logging.conf')
# create logger
logger = logging.getLogger('root')
PORT_NUMBER=8052
app = dash.Dash( # How to use app.logger on the registered pages contained in package pages/?
__name__,
suppress_callback_exceptions=True,
use_pages=True,
external_stylesheets = [ dbc.themes.BOOTSTRAP, 'https://codepen.io/chriddyp/pen/bWLwgP.css' ]
)
navbar = dbc.NavbarSimple( dbc.DropdownMenu( [
dbc.DropdownMenuItem(page["name"], href=page["path"])
for page in dash.page_registry.values() if page["module"] != "pages.not_found_404"
], nav=True, label="More Pages" )
brand="Multipage App", color="primary", dark=True, className="bg-dark text-center text-warning",
)
app.layout = dbc.Container( [navbar, dash.page_container], fluid=True )
if __name__ == '__main__':
app.logger.info('Starting ...') # This is logged as expected but further log messages are missing!
app.run_server(debug=True, port=PORT_NUMBER)
app.logger.info('Finished')
I collected the following contents of pages/__init__.py online but I’m no longer exactly sure why:
from dash import html as _html
def page_not_found(pathname):
return _html.P("No page '{}'".format(pathname))
It was in pages/some page.py where I had tried adding
from ..app import app
before
# **Creating a new logger like this seems to interfere with app.logger so I wanted to use app.logger on this page, too**
logger = logging.getLogger(__name__)
#
dash.register_page(__name__, path="/"+Path(__file__).stem)
def layout(**kwargs):
dash_components = [ dbc.Row(...) ]
dash_components += dcc.Markdown(...)
return html.Div( dash_components )
@callback(
Output('label', 'children'),
Input('input-text', 'value')
)
def handle(text : str):
logger.info(f'sending {text=} to label') # How to use app.logger instead of logger here?
return html.Div(text)
as mentioned above.
In the end I found out I had set up everything in the right way but forgotten while pursuing other projects that my app is already started automatically since I configured a batch file starting it for NSSM - the Non-Sucking Service Manager
Obviously, logging in a second instance started from CLI following the original routine necessarily interfered with the service whose log messages are shown as intended by the log file viewer of your choice.
I’m sorry for the confusion!
Although I’m ok now and would close this for my own purposes I’d just like to add that the question is not answered in the strict sense because the the code for each page - let’s say pages/any page.py - is still defining a separate logger in the line
logger = logging.getLogger(__name__)
which is the standard AFAIK. So I’m not following the recommendation to use Flask’s app.logger mentioning which I started my original question with. Whether this would make more sense or not the question how it could be done is still open.