How to create a script to run the application after pip install package?

Hi

I setup a python package with a Dash application inside. I would like to provide along with the package a kind of script in order to run the application. The idea for the end user is to do the following to be able to launch the application

# install the package
pip install my_package
# run the application
run_app

By doing this, it avoids the user to have to clone the repository, change to the app folder and run the app.py file.

The run_app file can be either a simple script provided as a script in setup.cfg or as an entry point in setup.cfg.

Thanks

Hi,

I haven’t tested this, but I guess you could do the following:

In setup.cfg:

[options.entry_points]
console_scripts =
    my-package-app = my_package.apps.app:main

Then in my_package/apps/app.py you would need the β€œusual”:

# ... app definition

if __name__ == "__main__":
    app.run_server()

For portability, you would probably need something to check if the default port is being used and change it if needed. Not sure how to do it in python though…

Please let me know if this works, I am very curious about it and this can be super useful. :slight_smile:

1 Like

Hi,

To make it to work I had to create a function and make the entry point to point to this function. It works but I have an error due to assets contents.

Here are the (fake) architecture of the package folder. You may note the app folder that contains the dash application in the app.py file and the run_app.py file, in the parent directory, in order to produce the entry point with a main() function.

my_package
β”œβ”€β”€ README.md
β”œβ”€β”€ environment.yml
β”œβ”€β”€ pyproject.toml
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ setup.cfg
└── src
    └── my_package
        β”œβ”€β”€ __init__.py
        β”œβ”€β”€ app
        β”‚   β”œβ”€β”€ __init__.py
        β”‚   β”œβ”€β”€ app.py
        β”‚   β”œβ”€β”€ app.wsgi
        β”‚   β”œβ”€β”€ assets
        β”‚   β”‚   β”œβ”€β”€ css
        β”‚   β”‚   β”‚   └── base.css
        β”‚   β”‚   β”œβ”€β”€ img
        β”‚   β”‚   β”‚   β”œβ”€β”€ scheme.png
        β”‚   β”‚   β”‚   └── screenshot1.png
        β”œβ”€β”€ some_utils.py
        └── run_app.py

Here is the end of my setup.cfg file where I define the entry point:

[options.entry_points]
console_scripts=
    run_app = my_package.run_app:main

Here is the run_app.py file. In short, I import the app.py file and run the application using the webbrowser module.
One issue is the assets folder, the content is not found … neither css nor images.

#coding: utf-8

import webbrowser
from threading import Timer
from pathlib import Path

from my_package.app import app

TITLE = """
MY FAMOUS APP 
"""

def main():
    """ Run the app from an entry point 
    TODO: need to check port is available and host ?
    """

    print(TITLE)

    # set up the url and a threading Timer
    host = "localhost"
    port = 8080
    folder = "app-name"
    url = f"http://{host}:{port}/{folder}/"
    Timer(10, webbrowser.open_new(url))

    # get back the location of the assets folder
    assets_folder = Path(app.__file__).parent / folder / "assets"
    app.app.assets_folder = assets_folder

    # run app
    app.app.run_server(
        host=host,
        port=port,
        debug=False
    )

I did two things. On a fresh conda environment, I got an error with te assets folder:

$ > run_app
Dash is running on http://localhost:8080/icp-ms-map/

 * Serving Flask app 'icp_ms_map.app.app' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://localhost:8080 (Press CTRL+C to quit)
127.0.0.1 - - [06/May/2022 15:47:56] "GET /icp-ms-map HTTP/1.1" 308 -
127.0.0.1 - - [06/May/2022 15:47:56] "GET /icp-ms-map/ HTTP/1.1" 200 -
127.0.0.1 - - [06/May/2022 15:47:57] "GET /icp-ms-map/_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [06/May/2022 15:47:57] "GET /icp-ms-map/_dash-dependencies HTTP/1.1" 200 -
127.0.0.1 - - [06/May/2022 15:47:57] "GET /icp-ms-map/assets/img/scheme.png HTTP/1.1" 404 -

Now If I run the same command from my home directory, in my dev environment (after a pip install -e .) it works fine and assets are loaded:

$ [git/my_package/] > pip install -e .
$ [git/my_package/] > cd
$ [~] run_app
Dash is running on http://localhost:8080/icp-ms-map/

 * Serving Flask app 'icp_ms_map.app.app' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://localhost:8080 (Press CTRL+C to quit)
127.0.0.1 - - [06/May/2022 15:48:50] "GET /icp-ms-map/ HTTP/1.1" 200 -
127.0.0.1 - - [06/May/2022 15:48:50] "GET /icp-ms-map/_dash-component-suites/dash/dcc/async-upload.js HTTP/1.1" 304 -
127.0.0.1 - - [06/May/2022 15:48:50] "GET /icp-ms-map/assets/css/base.css?m=1651237252.574377 HTTP/1.1" 304 -
127.0.0.1 - - [06/May/2022 15:48:50] "GET /icp-ms-map/assets/css/icpms.css?m=1651237252.5733213 HTTP/1.1" 304 -
127.0.0.1 - - [06/May/2022 15:48:50] "GET /icp-ms-map/assets/css/fontawesome.css?m=1651237252.5738108 HTTP/1.1" 304 -
127.0.0.1 - - [06/May/2022 15:48:50] "GET /icp-ms-map/_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [06/May/2022 15:48:50] "GET /icp-ms-map/_dash-dependencies HTTP/1.1" 200 -
127.0.0.1 - - [06/May/2022 15:48:50] "GET /icp-ms-map/_dash-layout HTTP/1.1" 200 -
127.0.0.1 - - [06/May/2022 15:48:50] "GET /icp-ms-map/_dash-dependencies HTTP/1.1" 200 -
127.0.0.1 - - [06/May/2022 15:48:50] "GET /icp-ms-map/assets/img/scheme.png HTTP/1.1" 200 -

Thank you for any help.

1 Like

Thanks for sharing this!

I have some ideas on how to fix this, but I would need to test them first. For instance, I am wondering if you’d need to explicitly add the assets folder to β€œpackage_data”, so it can be imported from the installed package.

I found the solution.

Actually, I had not created the MANIFEST.in file (I realize that maybe that was what you said by package data). In consequence, in the site-packages folder, the assets folder was absent. So now it works.

I will try to produce a working minimal app with the entry point.

2 Likes

Yes, that’s what I meant. Glad it worked, looking forward for the example.