Trying to combine flask and guizero - python-3.x

So i was trying flask when i got an funny idea. If i could combine guizero with my server i could make like a console for my simple server. So i began working when i stumbled over 2 problems.
Here's my code:
from flask import Flask, render_template
from guizero import App, PushButton, Text, TextBox
app = Flask(__name__)
app.debug = True
console = App(title='web server')
text_input = "no message"
def message():
text_input = textbox.get
textbox.clear
header = Text(console, text="Web server console", size= 50)
description = Text(console, text="type message here:")
textbox = TextBox(console)
button = PushButton(console, text="send", command=message)
#app.route('/')
def index():
return render_template('index.html', text= text_input)
#app.route('/next')
def next():
return render_template('game.html')
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
app.display()
The template index.html is just simply a paragraph with {{text}}. It does show the "no message" string.
Now i'm experiencing 2 problems with this code.
1: If i run it it only starts the server, but when i run it again it gives the "already in use" error and then opens the gui
2: If i use the gui the website won't update when i push the button, i think because the gui doesnt run in the same instance of the script as the server. And if it does i don't think the debug function works with variables in the script.
running the server on a raspi 3B on ethernet if that is important
i'm very new to flask and html so maybe i won't understand your answer but i'd be glad if you could help

I also am new to Flask but I think you have to make a new thread (either for the Flask app or the GUI). This makes sure that both Flask and the GUI can run simultaneously. Now you try to run two loops at the same time and tht doesn't work.

Related

Using Telegram Bot with Django

I am trying to use my telegram bot with Django. I want the code to keep running in the background. I am Using the apps.py to do this but there's one problem when the bot starts as it's an infinite loop, the Django server is never started.
Apps.py:
from django.apps import AppConfig
import os
class BotConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'bot'
def ready(self):
from . import jobs
if os.environ.get('RUN_MAIN', None) != 'true':
jobs.StartBot()
Jobs.py:
def StartBot():
updater = Updater("API KEY")
dp = updater.dispatcher
dp.add_handler(ChatMemberHandler(GetStatus, ChatMemberHandler.CHAT_MEMBER))
updater.start_polling(allowed_updates=Update.ALL_TYPES)
updater.idle()
What's the best way to run my bot in the background? while making sure that the Django server runs normally. I tried Django background tasks but it's not compatible with Django 4.0.
The purpose of Updater.idle is to keep the main thread alive because start_polling only starts some background threads that don't block the main thread. If you want to run other stuff in the main thread, skip updater.idle() and instead call Updater.stop manually when the program should shut down.
Disclaimer: I'm currently the maintainer of python-telegram-bot

Why doesn't my Selenium session stay logged in?

I'm working on using selenium to sign into GitHub and create a repository. A similar project that I had found, after login used "https://github.com/new" to go to the repo creation page. However, when I try to do that, it returns to an empty login page with the following url: "https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fnew".
I'm pretty lost and haven't found a good reason yet for why this would be happening.
PS. This is connected to a shell script, but the shell script is doing what it's supposed to so I didn't attach that code along with the Python that's being troublesome.
import sys
from selenium import webdriver
browser = webdriver.Safari()
def createProj():
folder_name = str(sys.argv[0])
browser.get("https://github.com/login")
try:
login_button = browser.find_elements_by_xpath("//*[#id='login_field']")[0]
login_button.click()
login_button.send_keys("Insert email here")
pass_button = browser.find_elements_by_xpath("//*[#id='password']")[0]
pass_button.click()
pass_button.send_keys("Insert password here")
submit_button = browser.find_elements_by_xpath("//*[#id='login']/form/div[4]/input[9]")[0]
submit_button.click()
except:
print("You're already signed in, no need to log in.")
browser.get("https://github.com/new")
if __name__ == "__main__":
createProj()

flask not responding with template

I am running a flask server in testing but the render_template() method is not responding
Here is my app.py
from flask import Flask, render_template, jsonify, request
from feeders import feeder
app = Flask(__name__)
#app.route("/", methods=["GET", "POST"])
def feed():
if request.method == "GET":
data = feeder.all_feed()
return render_template("feed.html", allfeed=data)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
I am using ThreadPoolExecutor for some of my tasks, here is how the all_feed() method looks like.
def all_feed():
with ThreadPoolExecutor(max_workers=7) as executor:
results = list(executor.map(get_feed, feeder_site_urls.values()))
print(results)
return results
I can see results on the terminal but the template is not rendering.
And yes all my templates are under templates/.
Edit: I can see that the flask is consuming memory (gradually increasing)
Apparently there was a bug in one of my templates
Always remember to run in DEBUG Mode.
Also create a .flaskenv file with following contents
FLASK_APP=app.py
FLASK_ENV=development
FLASK_RUN_PORT=8000
FLASK_RUN_HOST=0.0.0.0
Thanks to one of my friend

Configuring my Python Flask app to call a function every 30 seconds

I have a flask app that returns a JSON response. However, I want it to call that function every 30 seconds without clicking the refresh button on the browser. Here is what I did
Using apscheduler
. This code in application.py
from apscheduler.schedulers.background import BachgroundScheduler
def create_app(config_filname):
con = redis.StrictRedis(host= "localhost", port=6379, charset ="utf-8", decode_responses=True, db=0)
application = Flask(__name__)
CORS(application)
sched = BackgroundScheduler()
#application.route('/users')
#cross_origin()
#sched.scheduled_job('interval', seconds = 20)
def get_users():
//Some code...
return jsonify(users)
sched.start()
return application
Then in my wsgi.py
from application import create_app
application = create_app('application.cfg')
with application.app_context():
if __name__ == "__main__":
application.run()
When I run this appliaction, I get the json output but it does not refresh instead after 20 seconds it throws
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context(). See the
documentation for more information.
What am I doing wrong? I would appreciate any advise.
Apologies if this in a way subverting the question, but if you want the users to be sent every 30 seconds, this probably shouldn't be done in the backend. The backend should only ever send out data when a request is made. In order for the data to be sent at regular intervals the frontend needs to be configured to make requests at regular intervals
Personally I'd recommend doing this with a combination of i-frames and javascript, as described in this stack overflow question:
Auto Refresh IFrame HTML
Lastly, when it comes to your actual code, it seems like there is an error here:
if __name__ == "__main__":
application.run()
The "application.run()" line should be indented as it is inside the if statement

Handling atexit for multiple app objects with Flask dev server reloader

This is yet another flask dev server reloader question. There are a million questions asking why it loads everything twice, and this is not one of them. I understand that it loads everything twice, my question involves dealing with this reality and I haven't found an answer that I think addresses what I'm trying to do.
My question is, how can I cleanup all app objects at exit?
My current approach is shown below. In this example I run my cleanup code using an atexit function.
from flask import Flask
app = Flask(__name__)
print("start_app_id: ", '{}'.format(id(app)))
import atexit
#atexit.register
def shutdown():
print("AtExit_app_id: ", '{}'.format(id(app)))
#do some cleanup on the app object here
if __name__ == "__main__":
import os
if os.environ.get('WERKZEUG_RUN_MAIN') == "true":
print("reloaded_main_app_id: ", '{}'.format(id(app)))
else:
print("first_main_app_id: ", '{}'.format(id(app)))
app.run(host='0.0.0.0', debug=True)
The output of this code is as follows:
start_app_id: 140521561348864
first_main_app_id: 140521561348864
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
start_app_id: 140105598483312
reloaded_main_app_id: 140105598483312
* Debugger is active!
* Debugger pin code: xxx-xxx-xxx
^CAtExit_app_id: 140521561348864
Note that when first loaded, an app object with ID '864 is created. During the automatic reloading, a new app object with ID '312 is created. Then when I hit Ctrl-C (last line), the atexit routine is called and the original '864 app object is the one that is accessible using the app variable -- not the newer '312 app object.
I want to be able to do cleanup on all app objects floating around when the server closes or is Ctrl-C'd (in this case both '864 and '312). Any recs on how to do this?
Or alternately, if I could just run the cleanup on the newer '312 object created after reloading I could also make that work -- however my current approach only lets me cleanup the original app object.
Thanks.
UPDATE1: I found a link that suggested using try/finally instead of the atexit hook to accomplish what I set out to do above. Switching to this results in exactly the same behavior as atexit and therefore doesn't help with my issue:
from flask import Flask
app = Flask(__name__)
print("start_app_id: ", '{}'.format(id(app)))
if __name__ == "__main__":
import os
if os.environ.get('WERKZEUG_RUN_MAIN') == "true":
print("reloaded_main_app_id: ", '{}'.format(id(app)))
else:
print("first_main_app_id: ", '{}'.format(id(app)))
try:
app.run(host='0.0.0.0', debug=True)
finally:
print("Finally_app_id: ", '{}'.format(id(app)))
#do app cleanup code here
After some digging through the werkzeug source I found the answer. The answer is that it isn't possible to do what I wanted -- and this is by design.
When using the flask dev server (werkzeug) it isn't possible to cleanup all existing app objects upon termination (e.g. ctrl-C) because the werkzeug server catches the keyboardinterrupt exception and "passes" on it. You can see this in the last lines of werkzeug's _reloader.py in the run_with_reloader function:
def run_with_reloader(main_func, extra_files=None, interval=1,
reloader_type='auto'):
"""Run the given function in an independent python interpreter."""
import signal
reloader = reloader_loops[reloader_type](extra_files, interval)
signal.signal(signal.SIGTERM, lambda *args: sys.exit(0))
try:
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
t = threading.Thread(target=main_func, args=())
t.setDaemon(True)
t.start()
reloader.run()
else:
sys.exit(reloader.restart_with_reloader())
except KeyboardInterrupt:
pass
If you replace the above "except KeyboardInterrupt:" with "finally:", and then run the second code snippet in the original question, you observe that both of the created app objects are cleaned up as desired. Interestingly, the first code snippet (that uses #atexit) still doesn't work as desired after making these changes.
So in conclusion, you can cleanup all existing app objects when using the flask dev server, but you need to modify the werkzeug source to do so.

Resources