patternpythonflaskMinor
Python GUI by QtWebkit and Flask
Viewed 0 times
flaskandpythonqtwebkitgui
Problem
I'm new to Python. For learning purposes, I want to create desktop application by using QtWebKit and Flask. You can find the source code here
Main idea is:
It works correctly but I want to know:
My code is:
core module:
and then
Main idea is:
- create a form including a QWebview widget
- create a Flask app
- run Flask app on QWebview
It works correctly but I want to know:
- How can I improve my code?
- is this good way to create desktop apps?
My code is:
main.pyfrom core.Core import *
app = Flask(__name__)
from routes import *
if __name__ == '__main__':
main(app)core module:
core/Core.pyimport sys
from flask import Flask , render_template
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
from threading import Thread
class FlaskThread(QThread):
def __init__(self,app):
QThread.__init__(self)
self.app = app
def __del__(self):
self.wait()
def run(self):
self.app.run()
def main(app):
th = FlaskThread(app)
th.start()
#qt init
qtapp = QApplication(sys.argv)
qtapp.aboutToQuit.connect(lambda : th.terminate())
webview = QWebView()
webview.load(QUrl('http://localhost:5000'))
webview.show()
sys.exit(qtapp.exec_())and then
routes.pyfrom main import *
@app.route('/')
def index():
#return 'hi'
return render_template('index.html')Solution
Your imports and module structure seems like an incredible mess. Yet your application only contains 3 files. Let's try and improve that.
Value your namespaces
Preferably in an interactive session, will give you an insight of how you should approach problems in Python. In your case, it is the last line
The core idea is to control where symbols can be found without risk of overriding them (or doing so knowingly). As such,
or
This also means that you should removed unnecessary imports.
Avoid circular imports
I'm talking about having
One of the major issue with circular import is that one of them might bring an half-loaded module, (mainly) leading to
Why do you need to
Why do you need to
Don't over-split your code
Modules are good since they allow you to differentiate purposes for pieces of codes. But too much modules makes the code unmanageable.
At this stage of development you could still have all your code in a single file without loosing readability. But I imagine that you'll want to make your application grow and I understand your need to split it into different modules.
You made a good job identifying purposes:
But I think you made a mistake making your GUI module "secondary". The GUI is the entry point of the application for your users, I would have made it the main module.
Then you can put
You should also try to name your modules relative to what they do overall.
New layout
The few more changes I made contains:
Value your namespaces
import thisPreferably in an interactive session, will give you an insight of how you should approach problems in Python. In your case, it is the last line
Namespaces are one honking great idea -- let's do more of those! which is at issue.The core idea is to control where symbols can be found without risk of overriding them (or doing so knowingly). As such,
from import * is a bad practice and should either be:import or
from import , ..., This also means that you should removed unnecessary imports.
Avoid circular imports
I'm talking about having
from main import in routes.py and from routes import in main.py.One of the major issue with circular import is that one of them might bring an half-loaded module, (mainly) leading to
NameErrors.Why do you need to
import routes in the first place? Nothing is used from that in main.py, so you can remove it.Why do you need to
import main in the first place? To be able to use render_template and the app object? Well, you should import render_template in routes.py and create app in there instead.Don't over-split your code
Modules are good since they allow you to differentiate purposes for pieces of codes. But too much modules makes the code unmanageable.
At this stage of development you could still have all your code in a single file without loosing readability. But I imagine that you'll want to make your application grow and I understand your need to split it into different modules.
You made a good job identifying purposes:
- a module to manage your webapp (
routes.py);
- a module to manage your GUI (in case you'll want to get something better than a
QWebViewin the future).
But I think you made a mistake making your GUI module "secondary". The GUI is the entry point of the application for your users, I would have made it the main module.
Then you can put
routes.py into its own webapp (or whatever name fits its purpose more) folder. This will allow you to keep everything related to the "Web" part of your application in a single place. Try to at least separate your routes from your utilities functions.You should also try to name your modules relative to what they do overall.
main.py is not a good name.New layout
pyfladesk.pyimport sys
from PyQt4.QtCore import QThread, QUrl
from PyQt4.QtGui import QApplication
from PyQt4.QtWebKit import QWebView
PORT = 5000
ROOT_URL = 'http://localhost:{}'.format(PORT)
class FlaskThread(QThread):
def __init__(self, application):
QThread.__init__(self)
self.application = application
def __del__(self):
self.wait()
def run(self):
self.application.run(port=PORT)
def provide_GUI_for(application):
qtapp = QApplication(sys.argv)
webapp = FlaskThread(application)
webapp.start()
qtapp.aboutToQuit.connect(webapp.terminate)
webview = QWebView()
webview.load(QUrl(ROOT_URL))
webview.show()
return qtapp.exec_()
if __name__ == '__main__':
from webapp.routes import app
sys.exit(provide_GUI_for(app))webapp/routes.pyfrom flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')The few more changes I made contains:
- improved naming a bit (not so much, you might come up with better names too);
- converting magic values to constants so they can easily be spotted and changed;
- used the callable
webapp.terminatedirectly instead of creating alambda.
Code Snippets
import thisimport <something>from <something> import <required_name1>, ..., <required_nameN>import sys
from PyQt4.QtCore import QThread, QUrl
from PyQt4.QtGui import QApplication
from PyQt4.QtWebKit import QWebView
PORT = 5000
ROOT_URL = 'http://localhost:{}'.format(PORT)
class FlaskThread(QThread):
def __init__(self, application):
QThread.__init__(self)
self.application = application
def __del__(self):
self.wait()
def run(self):
self.application.run(port=PORT)
def provide_GUI_for(application):
qtapp = QApplication(sys.argv)
webapp = FlaskThread(application)
webapp.start()
qtapp.aboutToQuit.connect(webapp.terminate)
webview = QWebView()
webview.load(QUrl(ROOT_URL))
webview.show()
return qtapp.exec_()
if __name__ == '__main__':
from webapp.routes import app
sys.exit(provide_GUI_for(app))from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')Context
StackExchange Code Review Q#114221, answer score: 9
Revisions (0)
No revisions yet.