Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to complex applications. It began as a simple wrapper. Let us quickly configure Flask and spin up a web server in our local machine. Create a file main.py in the todoserviceflask directory: from flask import Flask app = Flask(name) @app.route('/') def helloworld: return 'Hello World!' After importing Flask, we set up a route. A route is specified by a URL pattern, an HTTP method, and a. Socketio=SocketIO Instance Flask SocketIO instance (if specified, uses socketio.run instead of app.run for Flask application) Should work on windows/linux/mac with no isssues. Develop your app as you would normally do, add flaskwebgui at the end or for tests. Flaskwebgui doesn't interfere with your way of doing a flask application it just helps converting it into a desktop app more easily with pyinstaller or pyvan.
Installing Flask installs the
flask
script, a Click command lineinterface, in your virtualenv. Executed from the terminal, this script givesaccess to built-in, extension, and application-defined commands. The --help
option will give more information about any commands and options.App.py — This contains Flask APIs that receives sales details through GUI or API calls, computes the predicted value based on our model and returns it. Request.py — This uses requests module to call APIs defined in app.py and displays the returned value. FLASKAPP=hello.py flask run. You should see something like. Running on in your terminal. And if you visit that link in your browser, you'll see a page with just Hello World. Example App: Penn Club Review. Note: The code for this project can be found at this repository on GitHub.
Application Discovery¶
The
flask
command is installed by Flask, not your application; it must betold where to find your application in order to use it. The FLASK_APP
environment variable is used to specify how to load the application.Unix Bash (Linux, Mac, etc.):
Windows CMD:
Windows PowerShell:
While
FLASK_APP
supports a variety of options for specifying yourapplication, most use cases should be simple. Here are the typical values:The file
wsgi.py
is imported, automatically detecting an app(app
). This provides an easy way to create an app from a factory withextra arguments.FLASK_APP=hello
The name is imported, automatically detecting an app (
app
) or factory(create_app
).FLASK_APP
has three parts: an optional path that sets the current workingdirectory, a Python file or dotted import path, and an optional variablename of the instance or factory. If the name is a factory, it can optionallybe followed by arguments in parentheses. The following values demonstrate theseparts:FLASK_APP=src/hello
Sets the current working directory to
src
then imports hello
.FLASK_APP=hello.web
Imports the path
hello.web
.FLASK_APP=hello:app2
Uses the
app2
Flask instance in hello
.FLASK_APP='hello:create_app('dev')'
The
create_app
factory in hello
is called with the string 'dev'
as the argument.If
FLASK_APP
is not set, the command will try to import “app” or“wsgi” (as a “.py” file, or package) and try to detect an applicationinstance or factory.Within the given import, the command looks for an application instance named
app
or application
, then any application instance. If no instance isfound, the command looks for a factory function named create_app
ormake_app
that returns an instance.When calling an application factory, if the factory takes an argument named
script_info
, then the ScriptInfo
instance is passed as akeyword argument. If the application factory takes only one argument and noparentheses follow the factory name, the ScriptInfo
instanceis passed as a positional argument. If parentheses follow the factory name,their contents are parsed as Python literals and passes as arguments to thefunction. This means that strings must still be in quotes.Run the Development Server¶
The
run
command will start the development server. Itreplaces the Flask.run()
method in most cases.Warning
Do not use this command to run your application in production.Only use the development server during development. The development serveris provided for convenience, but is not designed to be particularly secure,stable, or efficient. See Deployment Options for how to run in production.
Open a Shell¶
To explore the data in your application, you can start an interactive Pythonshell with the
shell
command. An applicationcontext will be active, and the app instance will be imported.Use
shell_context_processor()
to add other automatic imports.Environments¶
Changelog
The environment in which the Flask app runs is set by the
FLASK_ENV
environment variable. If not set it defaults toproduction
. The other recognized environment is development
.Flask and extensions may choose to enable behaviors based on theenvironment.If the env is set to
development
, the flask
command will enabledebug mode and flaskrun
will enable the interactive debugger andreloader.Watch Extra Files with the Reloader¶
Mac service battery warning. When using development mode, the reloader will trigger whenever yourPython code or imported modules change. The reloader can watchadditional files with the
--extra-files
option, or theFLASK_RUN_EXTRA_FILES
environment variable. Multiple paths areseparated with :
, or ;
on Windows.Debug Mode¶
Debug mode will be enabled when
FLASK_ENV
is development
,as described above. If you want to control debug mode separately, useFLASK_DEBUG
. The value 1
enables it, 0
disables it.Environment Variables From dotenv¶
Rather than setting
FLASK_APP
each time you open a new terminal, you canuse Flask’s dotenv support to set environment variables automatically.If python-dotenv is installed, running the
flask
command will setenvironment variables defined in the files .env
and .flaskenv
.This can be used to avoid having to set FLASK_APP
manually every time youopen a new terminal, and to set configuration using environment variablessimilar to how some deployment services work.Variables set on the command line are used over those set in
.env
,which are used over those set in .flaskenv
. .flaskenv
should beused for public variables, such as FLASK_APP
, while .env
should notbe committed to your repository so that it can set private variables.Directories are scanned upwards from the directory you call
flask
from to locate the files. The current working directory will be set to thelocation of the file, with the assumption that that is the top level projectdirectory.The files are only loaded by the
flask
command or callingrun()
. If you would like to load these files when running inproduction, you should call load_dotenv()
manually.Setting Command Options¶
Click is configured to load default values for command options fromenvironment variables. The variables use the pattern
FLASK_COMMAND_OPTION
. For example, to set the port for the runcommand, instead of flaskrun--port8000
:These can be added to the
.flaskenv
file just like FLASK_APP
tocontrol default command options.Disable dotenv¶
The
flask
command will show a message if it detects dotenv files butpython-dotenv is not installed.You can tell Flask not to load dotenv files even when python-dotenv isinstalled by setting the
FLASK_SKIP_DOTENV
environment variable.This can be useful if you want to load them manually, or if you’re usinga project runner that loads them already. Keep in mind that theenvironment variables must be set before the app loads or it won’tconfigure as expected.Environment Variables From virtualenv¶
If you do not want to install dotenv support, you can still set environmentvariables by adding them to the end of the virtualenv’s
activate
script. Activating the virtualenv will set the variables.Unix Bash,
venv/bin/activate
:Windows CMD,
venvScriptsactivate.bat
:It is preferred to use dotenv support over this, since
.flaskenv
can becommitted to the repository so that it works automatically wherever the projectis checked out.Custom Commands¶
The
flask
command is implemented using Click. See that project’sdocumentation for full information about writing commands.This example adds the command
create-user
that takes the argumentname
.This example adds the same command, but as
usercreate
Old mac app icons. , a command in agroup. This is useful if you want to organize multiple related commands.See Testing CLI Commands for an overview of how to test your customcommands.
Registering Commands with Blueprints¶
If your application uses blueprints, you can optionally register CLIcommands directly onto them. When your blueprint is registered onto yourapplication, the associated commands will be available to the
flask
command. By default, those commands will be nested in a group matchingthe name of the blueprint.You can alter the group name by specifying the
cli_group
parameterwhen creating the Blueprint
object, or later withapp.register_blueprint(bp,cli_group='..')
.The following are equivalent:Specifying
cli_group=None
will remove the nesting and merge thecommands directly to the application’s level:Application Context¶
Commands added using the Flask app’s
cli
command()
decorator will be executed with an applicationcontext pushed, so your command and extensions have access to the app and itsconfiguration. If you create a command using the Click command()
decorator instead of the Flask decorator, you can usewith_appcontext()
to get the same behavior.If you’re sure a command doesn’t need the context, you can disable it:
Plugins¶
Flask will automatically load commands specified in the
flask.commands
entry point. This is useful for extensions that want to add commands whenthey are installed. Entry points are specified in setup.py
Inside
flask_my_extension/commands.py
you can then export a Clickobject:Once that package is installed in the same virtualenv as your Flask project,you can run
flaskmy-command
to invoke the command.Custom Scripts¶
When you are using the app factory pattern, it may be more convenient to defineyour own Click script. Instead of using
FLASK_APP
and letting Flask loadyour application, you can create your own Click object and export it as aconsole script entry point.Create an instance of
FlaskGroup
and pass it the factory:Define the entry point in
setup.py
:Install the application in the virtualenv in editable mode and the customscript is available. Note that you don’t need to set
FLASK_APP
.Errors in Custom Scripts
When using a custom script, if you introduce an error in yourmodule-level code, the reloader will fail because it can no longerload the entry point.
The
flask
command, being separate from your code, does not havethis issue and is recommended in most cases.PyCharm Integration¶
PyCharm Professional provides a special Flask run configuration. Forthe Community Edition, we need to configure it to call the
flaskrun
CLI command with the correct environment variables. These instructionsshould be similar for any other IDE you might want to use.In PyCharm, with your project open, click on Run from the menu bar andgo to Edit Configurations. You’ll be greeted by a screen similar tothis:
There’s quite a few options to change, but once we’ve done it for onecommand, we can easily copy the entire configuration and make a singletweak to give us access to other commands, including any custom ones youmay implement yourself.
Click the + (Add New Configuration) button and select Python. Givethe configuration a name such as “flask run”. For the
flaskrun
command, check “Single instance only” since you can’t run the servermore than once at the same time.Select Module name from the dropdown (A) then input
flask
.The Parameters field (B) is set to the CLI command to execute(with any arguments). In this example we use
run
, which will runthe development server.You can skip this next step if you’re using Environment Variables From dotenv. We need toadd an environment variable (C) to identify our application. Clickon the browse button and add an entry with
FLASK_APP
on the left andthe Python import or file on the right (hello
for example). Add anentry with FLASK_ENV
and set it to development
.Next we need to set the working directory (D) to be the folder whereour application resides.
If you have installed your project as a package in your virtualenv, youmay untick the PYTHONPATH options (E). This will more accuratelymatch how you deploy the app later.
Click Apply to save the configuration, or OK to save and close thewindow. Select the configuration in the main PyCharm window and clickthe play button next to it to run the server.
Now that we have a configuration which runs
flaskrun
from withinPyCharm, we can copy that configuration and alter the Script argumentto run a different CLI command, e.g. flaskshell
.EDIT 2019.05.03: The content order was change and the ideas were express more succinctly.
Having a single executable file could be a great advantage in so many cases and nowadays more a more desktop applications are using web technologies (React Native, Cordova, Ionic, etc.). It was time for the Python stack to join the Group via PyFlaDesk, a simple script to combine Flask, Qt and PyInstaller to create desktop Apps.
I wanted to create a single executable desktop application and since PyInstaller was there for a while I thought it would be pretty easy, it turns out that after after trying lots of solutions from Stack overflow, Quora and several blogs without success, I decided to post how I managed to solve the problem.
Note: A full list of the resources mentioned is below
If you just want to read the solution, scroll down to the solution section
The Problem
Well, Flask is a WEB framework (or Microframework as it desribes itself), used to create WEBsites that will be served by a WEB server and view from a WEB browser. Problems emerge when we try to replace 'WEB' with desktop in the previous sentence, we are trying to force something built for a particular scenario with its limitations to work in a completely different one.
Motivation
Desktop applications aren't the most popular use for Python, those positions belongs to Web Development, DevOps and Data Science and, among the technologies used in the Web Development, Django and Flask are the most popular frameworks.
Using the tools one already knows for something completely different is a great advantage, in this case we want to create a desktop app with a single executable file from a web app built with Flask.
Some of the main advantages of the self-contained (also known as portable) software are:
- No virtual environment required.
- Knowing which software is installed in the destination machine isn't necessary.
- No installation required, just copy and paste or execute from removable drive.
- Easier to tell the final user where is the program and how to execute it.
- Harder (yet not impossible) to reverse engineer the software.
There are some obvious disadvantages such as:
- Since all dependencies are included, files could get BIG (Hello World app in Flask is about 25MB).
- No version control support for binaries.
- If you consume self-contained software you have to trust your provider about its safety.
- Working with external files, databases and other external sources has to be strongly tested.
This are some points to consider, they could be advantages or disadvantages depending on the case:
- You treat the software as a black box.
- When a new version is released you just replace the file and you're done.
Flask comes into the action
If you attempt to port a web app to a desktop one without changing the framework chances are you will use a lightweight framework like Flask. Now, how do you create a desktop app? Using a desktop framework (Qt, Tk, wx, etc), the most commonly used framework for this task is Qt. The idea is to create a minimal web browser capable of rendering HTML and then, execute the flask application server and browse to the url of the server inside this browser.
But what are the differences between creating a web browser and using the systems default? Well, first of all, you assume there will be one, and that that one would be able to render all the HTML, CSS and JS you are using, that could not be the case. More often than not we found ourselves developing software for old operating systems (aka Windows XP o older).
Sounds easy and actually it can be done, I was contributing to a script to achieve this very goal PyFladesk. There are some concerns about which version of Qt is the appropriate and the convenience of one over the other.
Note: If all you use is Flask for served static or pseudo static content you could tried Frozen Flask.
Solution
After reading all the previous posts and some of the PyInstaller docs. I found that some people actually solved it! But, the solution they propose was editing the spec file, which is generated after a first run of PyInstaller. I thought that solution was a hack and not the proper way to achieve what I wanted.
So I tried to understand what the changes in the spec file did and it turned out that that changes was to copy the folders Flask uses into the file directory/file (Actually one of the proposed solutions was build and then copy paste the folders, but besides being unpractical it wouldn't work with one file builds). After a little reasearch, I came across the command line arguments to achieve the same.
Windows:
Mac app to open large tif files. Linux (NOT TESTED):
This will create a folder
dist
with our executable ready to be shipped. The executable will open the main window of our app.It first started as a contribution for the PyFladesk project and then, I realize that since Qt is quite big, our executable were big too. The example app of that repository is 70 MB (much of which was the Qt Component for displaying HTML (WebEngine)). This is reasonable taking into account that we were shipping a self contain web browser.
There is no simple solution to the size problem but some suggestions are proposed in a following section.
Tutorial
If you haven't already, install it with pip (if you use virtual environments you should install it inside it)
Some parameters to consider:
F
- Bundles everything in a single filew
- Avoid displaying a console--add-data
- Add Folders to the directory/executable
Since Flask relies on a directory structure you should pass it to the folder, in the example case we only have two folders:
templates
and static
, in case you use a database or some other directory structure you may adapt this.Note: For more complex scenarios check the PyInstaller Docs
The Size Problem
Is the project using as few dependencies as possible? If yes, continue reading, if not check and then come back. Make sure you create a virtual environment for your project and execute PyInstaller from there, if the size is still big, I recommend you to check one of these:
- Use Virtual Environments and install everything you need there, including PyInstaller (but nothing more!)
- Check if all your dependences are really necessary, try to use the standard library when possible
- Check if your biggest dependencies could be replaced with lightweight alternatives
- Use one-dir option and then see what are the biggest dlls and if you can exclude them
- Use the ArchiveViewer.py script that's part of PyInstaller and exclude everything you don't need
Conclusion
Using PyInstaller and Flask is not as hard as people may experience if you have the correct knowledge but it requires a bit of work to get a clean, lightweight file. However, it's possible to create executable with complex apps, with special directory structure, databases and so on, but don't expect that to be a tiny file.
Additional Resources
The following are the pages where this topic was mentioned and I couldn't find a proper answer:
Flask App Machine Learning
- Flask application built using pyinstaller not rendering index.html - jinja2.exceptions.TemplateNotFound (Stack Overflow)
- Pyinstaller on Flask app, import error (Stack Overflow)
- Using Pyinstaller on Python Flask Application to create Executable (Stack Overflow)
- Python 2.7.12, trying to build an executable file using pyinstaller. I keep getting the below error (Stack Overflow)
- Can I convert a Flask application into an executable file that runs on Windows like an .exe file? (Quora)
- Is it possible to deploy/distribute Flask as an executable for desktop use? (Reddit)
- Flask and pyinstaller notice (Personal Website)