Python Tkinter with Flask API and Subprocess - python

Could I run a function from another python file inside subprocess?
I use pyinstaller to convert the tkinter to an executable file. As much as possible I would like to deploy/run the .exe file to another computer without installing python.
#gui.py
from tkinter import *
import os
import subprocess
root = Tk()
root.geometry("300x150")
def backendStart():
subprocess.Popen(["test.py"], shell=True)
label = Label(root, text="Connection String", fg="grey", font=("Helvetica", 15, "bold"))
label.pack(pady=(0,3))
root.after_idle(backendStart)
root.mainloop()
Here is my sample app.py
from flask import Flask, jsonify
from flask_restful import Api, Resource
from flask_socketio import SocketIO, emit
from flask_cors import CORS
import random
from connection import cursor
app = Flask(__name__)
app.config["DEBUG"] = True
api = Api(app)
CORS(app)
socketio = SocketIO(app, cors_allowed_origins="*")
#socketio.on("connect")
def ClientConnection():
print("Client is Connected")
#socketio.on("realtime", namespace="/sample-socket")
def RealTimeData():
while True:
num = random.randint(1, 100)
emit("data", {"random": num})
socketio.sleep(1)
#socketio.on("disconnect")
def ClientDisconnected():
print("client has disconnected")
class HomePage(Resource):
def get(self):
return jsonify(msg="hello world")
api.add_resource(HomePage, "/")
if __name__ == '__main__':
socketio.run(app, host="192.168.0.109", port=5000)
Currently I made a .spec file for configurating the names, logo, and files/libs included. The .exe file work as long as I pasted the app.py inside the build folder along with the connection.py for the database.
But with this set up I do need to install python along with the libraries I used for the app.py and connection.py

Could I run a function from another
python file inside subprocess?
you can use multiprocessing.Process()
Edit:
For an expert's answer, see here
Alternate solution:
Lets say you want to run app.exe (which is app.py), you can pack all of them into one folder (--onedir) and put those exe's and pyd's subfolders.... together, like
gui
----flask (and other folders)
----*.pyd
----app.exe
----gui.exe
----python39.dll
you will need a custom spec file to do that.
see https://pyinstaller.readthedocs.io/en/stable/spec-files.html#multipackage-bundles

Related

Importing modules from parent folder does not work when running flask app

I am trying to import module from file in my parent directory but is not working
Here is how my directory looks like :
Here is how my main.py file looks like :
import sys
path_modules="./Utils"
sys.path.append(path_modules)
from functools import lru_cache
from flask import Flask, render_template, request
import Utils.HardSoftClassifier as cl
import Utils.prediction_utils as ut
import Utils.DataPrepper_reg as prep
app = Flask(__name__)
#app.route('/')
#app.route('/index')
def index():
return render_template('index.html')
#app.route('/viz')
def viz():
return render_template('viz.html')
if __name__=="__main__":
# import os
# os.system("start microsoft-edge:http:\\localhost:5000/")
app.run(debug=True)
Here is my flaks output :
In order to make a package importable, it must have an (optionally empty) __init__.py file in its root. So first create an empty __init__.py file in the Utils directory.
Furthermore, you don't have to alter the import path, since you start the Flask app from the Clean_code, the simple relative importing will work. So the first three line can be removed from main.py.

Python 3.8 module duplication and app object scope within imported functions

I'm confused about import of custom modules. As you can see in the code below, in main I first import all libraries needed by everything AND that I duplicated those imports in my i_setup_functions.py file. Leaving any of them out of either file created errors. Same with duplication of "app = Flask(name)". I really hope that redundancy is not correct and there is some simple way to fix this. All I want to do is include setup for sessions, email, data connection, etc. Only showing sessions here for simplicity sake.
BTW: The entire app worked bug-free until I tried to modularize.
Error message:
RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret.
That error message points to a line in a function in the middle of main.py that tries to create a session.
Thanks for any ideas you all can share!
main.py:
from flask import session
import random
from datetime import datetime, timedelta
from i_setup_functions import setup_sessions
app = Flask(__name__)
# is the following line even necessary in either module?
application = app
setup_sessions()
setup_mail()
setup_logging()
[snip]
# Error here:
​session["id_user"] = id_user
i_setup_functions.py
from flask import session
import random
from datetime import datetime, timedelta
from i_setup_functions import setup_sessions
app = Flask(__name__)
application = app
def setup_sessions():
random.seed(datetime.now())
app.config['SECRET_KEY'] = str(random.randint(1, 500)) + "jibber" + str(random.randint(1, 500)) + "jabber"
app.permanent_session_lifetime = timedelta(days=30)
return True
You are creating two (or more?) separate apps and setting the SECRET_KEY to the one that isn't serving your application.
To fix this remove all app = Flask(__name__) calls from all modules except main.py. Then, pass the app you create in main.py to all the places you need it.
from flask import session
import random
from datetime import datetime, timedelta
from i_setup_functions import setup_sessions
app = Flask(__name__)
setup_sessions(app)
setup_mail(app)
setup_logging(app)
[snip]
​session["id_user"] = id_user

python unittest ModuleNotFoundError: No module named <...>

I tried to crate simple Python project with flask and unittest. Structure is quite simple:
classes
|-sysinfo
|static
|templates
|- index.html
|- layout.html
|__init__.py
|sysinfo.py
|printinfo.py
tests
|test_sysinfo.py
README.md
requirments.txt
Very simple class in printinfo.py:
#!/usr/bin/python
import psutil
import json
class SysInfo:
.......
def displayInfo(self):
.......
return json.dumps(self.__data)
And simple flask server run with sysinfo.py:
from flask import Flask, flash, redirect, render_template, request, session, abort
from printinfo import SysInfo
import json
obj1 = SysInfo("gb")
app = Flask(__name__)
#app.route('/')
def index():
var = json.loads(obj1.displayInfo())
return render_template('index.html',**locals())
#app.route('/healthcheck')
def healthcheck():
return "Ok"
#app.route("/api/all")
def all():
return obj1.displayInfo()
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
del obj1
I run it with python sysinfo.py staying in classes/sysinfo folder and everything works ok.
So I decided to run unittest for my application. Put in classes/tests ( also tried classes/sysinfo/tests) file test_sysinfo.py with code:
import unittest
import printinfo
from sysinfo import sysinfo
import json
import sys
class TestFlaskApi(unittest.TestCase):
def setUp(self):
self.app = sysinfo.app.test_client()
def simple_test(self):
response = self.app.get('/health')
self.assertEqual(
json.loads(response.get_data().decode(sys.getdefaultencoding())),
{'healthcheck': 'ok'}
)
if __name__ == "__main__":
unittest.main()
And when I started it I can see error:
Error Traceback (most recent call last):
File "\Python\Python37-32\lib\unittest\case.py", line 59, in testPartExecutor
yield File "\Python\Python37-32\lib\unittest\case.py", line 615, in run
testMethod() File "\Python\Python37-32\lib\unittest\loader.py", line 34, in testFailure
raise self._exception ImportError: Failed to import test module: test_sysinfo Traceback (most recent call last): File
"\Python\Python37-32\lib\unittest\loader.py", line 154, in
loadTestsFromName
module = __import__(module_name) File "\classes\sysinfo\tests\test_sysinfo.py", line 2, in <module>
import printinfo ModuleNotFoundError: No module named 'printinfo'
I read several articles, some topics here on StackOverflow for my understanding it's related to project structure. I tried to create setup.py and setup.cfg. I managed to start it with this setup, but test still didn't work.
Could you please help me with minimum setup applicable for my case? All the material I found had written for specific case or too general. I cannot apply it for my case.
Follow flask tutorial I edit __init__.py file to start app from here:
from flask import Flask, flash, redirect, render_template, request, session, abort
from . import printinfo
import json
import os
obj1 = printinfo.SysInfo("gb")
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev'
)
obj1 = printinfo.SysInfo("gb")
#app.route('/')
def index():
var = json.loads(obj1.displayInfo())
return render_template('index.html', **locals())
#app.route('/healthcheck')
def healthcheck():
return "Ok"
#app.route("/api/all")
def all():
return obj1.displayInfo()
#del obj1
return app
Also environment variables should be set for Flask:
For Linux and Mac:
export FLASK_APP=sysinfo
export FLASK_ENV=development
For Windows cmd, use set instead of export:
set FLASK_APP=sysinfo
set FLASK_ENV=development
And run application:
flask run
It run application on localhost on port 5000 since development env set. Anyway I needed to add from . import printinfo into __init__.py.
Didn't try test, but think it should work. If interesting will update soon.
Just followed Flask tutorial. Created conftest.py and test_factory.py. Run Ok with pytest:
import pytest
from sysinfo import create_app
from sysinfo import printinfo
#pytest.fixture
def app():
app = create_app({
'TESTING': True
})
with app.app_context():
printinfo.SysInfo("gb")
yield app
Probably the same setup could be used with unittest. Didn't try.

Flask CLI command not in __init__.py file

I'm trying to add commands to my Flask app.
This is my __init__.py file:
import os
from flask import Flask
from flask_cors import CORS
from flask_mongoengine import MongoEngine
app = Flask(__name__)
CORS(app)
app.config.from_object(os.environ['APP_SETTINGS'])
db = MongoEngine(app)
import slots_tracker_server.views # noqa
If I add to it:
#app.cli.command()
def test_run():
print('here')
I can run flask test_run with no problems, but if I try to move the code to another file, for example: commands.py, I get the error Error: No such command "test_run". when trying to run the command.
What I'm missing?
Use click (the library behind Flask commands) to register your commands:
# commands.py
import click
#click.command()
def test_run():
print('here')
In your __init__.py import and register the commands:
# __init__.py
from yourapp import commands
from flask import Flask
app = Flask(__name__)
app.cli.add_command(commands.test_run)
Take a look at the official docs
In you commands.py you can add register function like that:
def register(app):
#app.cli.command(name='test_run', help="test_run command")
def register_test_run():
test_run()
# other commands to register
And then in your __init__.py import this register function
from flask import Flask
app = Flask(__name__)
from commands import register
register(app)
Notice, that you should import register after you've initialized your app.

Flask app does not use routes defined in another module

I can't get it to work to use one module that creates the Flask application object and runs it, and one module that implements the views (routes and errorhandlers). The modules are not contained in a Python package.
app.py
from flask import Flask
app = Flask('graphlog')
import config
import views
if __name__ == '__main__':
app.run(host=config.host, port=config.port, debug=config.debug)
views.py
from app import app
#app.route('/')
def index():
return 'Hello!'
config.py
host = 'localhost'
port = 8080
debug = True
I always get Flask's default "404 Not Found" page. If I move the contents of view.py to app.py however, it works. What's the problem here?
You have four modules here:
__main__, the main script, the file you gave to the Python command to run.
config, loaded from the config.py file.
views, loaded from the views.py file.
app, loaded from app.py when you use import app.
Note that the latter is separate from the first! The initial script is not loaded as app and Python sees it as different. You have two Flask objects, one referenced as __main__.app, the other as app.app.
Create a separate file to be the main entry point for your script; say run.py:
from app import app
import config
if __name__ == '__main__':
app.run(host=config.host, port=config.port, debug=config.debug)
and remove the import config line from app.py, as well as the last two lines.
Alternatively (but much uglier), use from __main__ import app in views.py.

Categories

Resources