Structuring Your Dash App. Choosing the right structure makes it... | by Edward Krueger | Towards Data Science

By Edward Krueger and Erin Oefelein
Put simply, Dash is a Python package that allows for the creation of “dashboards” in pure Python without using HTML, CSS or JavaScript. Since it’s programmable, it’s far more powerful than other dashboarding options.
In recent years there has been a major push towards making Python scripts into web applications. To some extent, even Jupyter Notebooks push Python in this direction. However, new tools, including Dash and Streamlit, make it easier to distribute Python by allowing users to write web applications as scripts.
You’ve completed your project and created an app to showcase your results. Now, you’d like to share your project insights by deploying your Dash app. This article will walk you through how to structure your app into a form that is easy to deploy!
If this tooling seems like a lot, it is. However, you don’t need to write it all out if you don’t want to. Not only have we provided the code in the following repo, but we’ve also made it a template. So, you can just hit the button “Use this template,” follow the instructions and start editing the code in the app/ directory.
github.com
We will be using a sample app created to showcase a project. Let’s take a quick look at the app we are deploying. The project by Erin is the result of scraping tiny house listings, storing the results as a CSV and visualizing the results in a Dash app. Some of the plots require a Mapbox and, therefore, a Mapbox token.
Before we get started, here is an overview of what we’ll cover.
We’ll cover:
Enough about Pipenv to get started
How to use Pipenv to install dependencies
How and why we install development dependencies
How and why we use Pre-commit hooks
How to set environmental variables
How to structure the repository
How to test all of our toolings
Managing your app’s virtual environment with the pipenv package is highly recommended as pipenv allows additional functionality such as:
the ability to automatically source an environment (.env) file.
the ability to specify app requirements in the Pipfile, circumventing the need to use them in production.
the specification of the Python version used in the virtual environment.
The functionalities provided by pipenv make it much easier to deploy your app. Should you wish to install pipenv at this point, you can do so by running:
pip install pipenv
towardsdatascience.com
Within your project folder, run:
pipenv install <your app dependencies>
Our Tiny Home Dashboard app uses Pandas, Dash and Plotly. So, to create our pipenv environment, we run:
pipenv install pandas dash plotly gunicorn
Note the addition of gunicorn. It’s important to include gunicorn in your Pipfile so that, should you wish to deploy to the Google Cloud Platform App Engine service or to build a Docker container for your app, both will work as expected.
The above pipenv command will create a Pipfile and a Pipfile.lock, containing your app’s dependencies.
Development dependencies are all of the dependencies that aren’t required for the app to run in production but enhance the developer experience or the code quality.
We’ll use the following development dependencies:
black will format your code.
pylint will check your app’s code style and make recommendations on the length of a line of code, the presence of unused variables, whether imports are correctly placed at the top of the module, etc.
pipenv-to-requirementswrites your app’s requirements to a requirements.txt file, required in this format by several Cloud providers to be correctly recognized.
pre-commit is what automates the checks you’d like to see on your code (here, black, pylint and pipenv-to-requirements) before your code is committed to your GitHub repo.
You can install them with pipenv install --dev --pre black pylint pipenv-to-requirements pre-commit.
Alternatively, take the following snippet from our template, paste it in your Pipfile and run pipenv install --dev --pre .
[dev-packages]black = "*"pylint = "*"pre-commit = "*"pipenv-to-requirements = "*"
Next, you will add the pre-commit-config.yaml file to your project by running:
touch pre-commit-config.yaml
*Note: To be recognized correctly, this file must be named pre-commit-config.yaml!
You can easily copy and paste our pre-commit-config.yaml file’s text using the text found below:
repos:    - repo: https://github.com/psf/black      rev: 19.10b0      hooks:        - id: black    - repo: https://github.com/pre-commit/pre-commit-hooks      rev: v2.5.0      hooks:        - id: check-added-large-files    - repo: local      hooks:        - id: pylint          name: pylint          entry: pylint app/          language: system          always_run: true          pass_filenames: false        - id: pipenv-to-requirements          name: pipenv-to-requirements          entry: pipenv_to_requirements          language: system          always_run: true          pass_filenames: false
If your folder isn’t a git repo, you’ll need to run git init before creating the pre-commit hooks. Now, use the pre-commit dev dependency (installed during the creation of your virtual environment) to install and set up the git hooks by running:
pipenv run pre-commit install
The pipenv package is again used to run the pre-commit hooks. Are you starting to see why we recommend it? Now pre-commit will run automatically when running git commit!
Here is how the file should look in your editor of choice:
Should you wish to read more on pre-commit hooks, check out our article below.
towardsdatascience.com
Environment variables are useful in making your app more secure. Rather than saving tokens within your script, you can reference them using an environment variable. Some examples of tokens used within your app may be connections to databases, third-party APIs, etc.
In our case, we use Mapbox to render the interactive folium maps of the U.S. Rather than saving our token within our script, we reference our token’s secret key using an environment variable.
To create an environment variable, you will first create an .env file with the following command:
touch .env
Next, create a .gitignore file and add the .env file you’ve just created to your .gitignore file as shown:
Within the .env file, we can now create our environment variable. To do this, specify the name of the variable, here named MAPBOX_TOKEN, and specify its value. We’ve hidden our token’s secret key here for security.
Now when running pipenv, your environment variables will be sourced and loaded from the .env file automatically. And, when running:
pipenv run echo $MAPBOX_TOKEN
Your token’s value will print to the console.
If you did not originally set up your token in this way, you can easily set your env variable equal to your app’s original name for the token (here mapbox_access_token) to avoid changing the token name in every place it occurs in your app:
Now that you have all the files necessary to deploy your app, you’ll want to make sure your app is set up to be understood and easily deployed to the Cloud.
Create a folder named app and save all the necessary files to the app folder so that your project is structured as shown:
It’s always a good idea to make sure everything is working as expected by running your app locally first! You don’t want to go through all the trouble of deploying your app to the Cloud to find it doesn’t work there, and then debugging on the premise that the issue is related to your Cloud deployment, only to find the issue is with the app itself!
Once you’ve confirmed your app works on your machine, you are ready to commit your work to GitHub!
If you haven’t already created a GitHub repo to backup your files, do so now. You can easily set up a GitHub repo by following these instructions. Stage and add your app files to the repo:
git add pre-commit-config.yaml Pipfile Pipfile.lock app/
And commit them with:
git commit -m "Update package management"
Now that your app is structured correctly and all files have been staged, to run the hooks against all of the app files, run:
This will display and execute the hooks you’ve implemented.
**Note: The pre-commit hook requires that files be staged to be discovered when running pipenv run pre-commit run --all-files
When using pre-commit hooks, you’ll need to add and stage your files twice, as black and pipenv-to-requirementswill make changes to your code, namely black will format your scripts and pipenv-to-requirements will create a requirements.txt file. This causes the version stored locally and the version you’ve staged to be committed to be out of sync.
Add the requirements.txt file that was just created via the pipenv-to-requirementshook by running:
git add requirements*
Once you’ve done this, push your files by running:
git commit -m "your-message"
Nice! Your app has been structured, cleaned up and saved to GitHub.
If you’d like to have a closer look and deeper understanding of the over process so far, have a look at our article below. Note: We use some different tooling, but the concepts are the same.
towardsdatascience.com
Our next article will walk you through how to deploy your Dash app using Google’s App Engine service. Deploying on this platform is convenient as there is no need to Dockerize your app, as is necessary when deploying to Google’s Cloud Run and Compute Engine services.
We hope you’ve enjoyed this article! For more content on data science, machine learning, and development check out Edward’s YouTube Channel and subscribe to my mailing list below to be the first to hear about new articles!