2

We have a web application developed using Flask that runs on a Windows server with clients that connect to it. We now have a use case where it is desired that the server and client be combined onto a laptop so that both server and client code run together and make it appear as a native Windows application.

Basically, we now have two requirements that we did not have before:

  1. Must be able to launch the browser from within Python.

  2. Must be able to terminate the Python (Flask) application on browser window close.

We have succeeded in item 1. Item 2 remains elusive. We have tried terminating the werkzeug server but the Python code keeps running. Seeking help from those that know.

6
  • So you want to detect for any browser if it successfully exited? Commented Sep 2, 2016 at 14:53
  • We're going to put Chrome on the laptop. Commented Sep 2, 2016 at 14:57
  • 1
    We run the python application, it starts the Flask web service, it starts Chrome in kiosk mode, Chrome loads the web GUI, the user is happy, the user finishes and clicks the close browser window button, python should stop the server and terminate. Commented Sep 2, 2016 at 14:59
  • 1
    Okay, so if you start Chrome, say using Popen, and that waits fot the process to exit, then checking the status code should let you determine when to halt the server Commented Sep 2, 2016 at 14:59
  • We found that we had to open Chrome in another process using the multiprocessing module so that it would not block and prevent the rest of the python code from running. To open the browser, we're using webbrowser.get(...).open(...). Commented Sep 2, 2016 at 15:05

5 Answers 5

1

After reading the docs more thoroughly and experimenting with the implementation, we found the following main code to satisfy the objective.

from multiprocessing import Process, freeze_support


def run_browser():
    import webbrowser
    chrome = webbrowser.get(r'C:\\Program\ Files\ (x86)\\Google\\Chrome\\Application\\chrome.exe --window-size=500,500 --app=%s')
    chrome.open('http://localhost:5000/gui')

def run_app():
    from app import webapp
    webapp.run() #debug=True) #, use_reloader=False)

if __name__ == '__main__':
    freeze_support()

    a = Process(target=run_app)
    a.daemon = True
    a.start()

    b = Process(target=run_browser)
    b.start()
    b.join()
Sign up to request clarification or add additional context in comments.

1 Comment

Hi do you know if its possible to change the name of the window as well as the logo from the default 'localhost:5000/gui' to anything else?
0

I do not currently have a Windows client here so I cannot exactly test what I am suggesting.

Using pywinauto you can check for a Window's name.

You could build a script that checks this in background and kills your Flask application when the requested browser window is not opened.

from pywinauto.findwindows import find_windows
if not find_windows(best_match='YOURWINDOWNAMEHERE'):
    # Do your kill

Comments

0

This is an easier way with flaskwebgui

from flaskwebgui import FlaskUI

app = Flask(__name__)
ui = FlaskUI(app)

ui.run()

flaskwebgui - Create desktop applications with Flask (or Django)!

https://pypi.org/project/flaskwebgui/

Comments

0

Here is an example for flaskwebgui.

I have used pyinstaller to convert the python-flask application to executable file.

I used Installforge to convert the build files to setup(installer) file.

Comments

0

I slightly modified the main answer to:

  • make it work with current Chrome version
  • make it usable out-of-the-box (include a minimal Flask server).

This works and exits the server when Chrome is closed:

from multiprocessing import Process, freeze_support
from flask import Flask

def run_browser():
    import webbrowser
    chrome = webbrowser.get(r'"C:\Program Files\Google\Chrome\Application\chrome.exe" %s')
    chrome.open('http://localhost:5000/')

def run_app():
    app = Flask("test")
    @app.route("/")
    def index():
        return "Hello world"
    app.run()

if __name__ == '__main__':
    freeze_support()  # Add support for when a program which uses multiprocessing has been frozen to produce a Windows executable. (Has been tested with py2exe, PyInstaller and cx_Freeze.) One needs to call this function straight after the if __name__ == '__main__' line of the main module.

    a = Process(target=run_app)
    a.daemon = True
    a.start()

    b = Process(target=run_browser)
    b.start()
    b.join()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.