Using a shared variable between routes and main in flask - python

I have a python flask server. In the main of my script, I get a variable from user that defines the mode of my server. I want to set this variable in main (just write) and use it (just read) in my controllers. I am currently using os.environ, but I 'm searching for more flasky way to use.
I googled and tried following options:
flask.g: it is being reset for each request; so, I can't use it inside controllers when it is being set somewhere else.
flask.session: it is not accessible outside request context and I can't set it in the main.
Flask-Session: like the second item, I can't set it in the main.

In main you use app.run() so app is avaliable in main. It should be also avaliable all time in all functions so you can try to use
app.variable = value
but flask has also
app.config
to keep any settings. See doc: Configuration Handling

Related

Python logging using modules

I have multiple modules, which are called by a principal script. Each one does log messages using logging Python builtin package.
How can I log an session ID, set during the execution of the main script, across all modules, without needing to push this variable in each module?
I have set up a python configuration file, called config, with:
import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(filename)s:%(lineno)s|%(funcName)3s()|%(asctime)s|%(levelname)s|%(message)s",
handlers=[
logging.FileHandler("debug.log"),
logging.StreamHandler()
]
)
Other modules are using this pre configured logging object, via import, so I am using this:
from config import logging
But I need to log an ID from my current session, my log should look like:
module_name.py:25|function_name()|2020-04-27 18:28:26,518|INFO|Session_ID=abc123|some_message_here
I have tried to put this variable in the config file, set it, and then use it in a function named "log_info" and "log_debug" in this file, but my output log does not trace python script name and function name any more.
Does anyone knows how to handle this situation?
I don't know if this is the 100% best solution, or for sure if it'll work in your situation, but I used it for something similar (verbosity printing levels that would persist across several scripts).
Create a Python file, named, say, sessionid. Inside that, define a top-level setting named id. To set your id, import sessionid and sessionid.id = 'some_id'. Then have your config file import sessionid as well and use sessionid.id as needed.
It took me a bit to figure out that I had to access it like that; changing it using from sessionid import id; id = 'some_id' only persists within the script that does so.
It would make sense to put the id variable in your config file, but only if you don't need to set it in the same script that also needs to from config import logging.

Server initialization incognita

I am trying to initialize a local server on Python.
How is possible that the server initialization that I show on the image below is working?
Funny enough, app.run is not crushing the program. I was expecting some error of the kind: "app" does not have any run method or "app" has not been defined or something like that.
From PEP 8:
Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants.
If you put your imports before you initialize and run app. It should pull in everything correctly and work.

Safest place for initilization code

My application has a datastore entry that needs to be initialized with some default values when the app is first deployed. I have a page that lets administrators of the app edit those values later, so it's a problem if the initialization code runs again and overwrites those edits.
I initially tried putting code in appengine_config.py, but that's clearly not correct, as any new values for the entity were overwritten after a few page loads. I thought about putting it in main.py, before the call to run_wsgi_app(), but it's my understanding that main.py is run whenever App Engine creates a new instance of the application. Warmup requests seem to have the same problem as appengine_config.py.
Is there a way to do what I'm trying to do?
Typically you could use appengine_config.py or an explicit handler.
If you use appengine_config.py your code should check for the values existence, and only when no value exists should it define a default.
My main concern with one only initialisation code in appengine_config.py is the check for existence of these initial values will be performed on every instance startup. If there is a lot to check that's an overhead on warm starts that you may not want.
For iany initialisation code for a new instance, you will have this problem of checking existence no matter what strategy you adopt, that is "Ensuring what ever process intialiases default values runs at most once".
Personally I would actually have a specific handler method that you call only once. And it then checks to make sure it shouldn't run before taking any action; In case it is called again

Django view alter global variable

My django app contains a loop, which is launched by the following code in urls.py:
def start_serial():
rfmon = threading.Thread(target=rf_clicker.RFMonitor().run)
rfmon.daemon = True
rfmon.start()
start_serial()
The loop inside this subthread references a global variable defined in global_vars.py. I would like to change to value of this variable in a view, but it doesn't seem to work.
from views.py:
import global_vars
def my_view(request):
global_vars.myvar = 2
return httpResponse...
How can a let the function inside the loop know that this view has been called?
The loop listens for a signal from a remote, and based on button presses may save data to the database. There are several views in the web interface, which change the settings for the remotes. While these settings are being changed the state inside the loop needs to be such that data will not be saved.
I agree with Ignacio Vazquez-Abrams, don't use globals.
Especially in your use case. The problem with this approach is that, when you deploy your app to a wsgi container or what have you, you will have multiple instances of your app running in different processes, so changing a global variable in one process won't change it in others.
And I would also not recommend using threads. If you need a long running process that handles tasks asynchronously(which seems to be the case), consider looking at Celery( http://celeryproject.org/). It's really good at it.
I will admit to having no experience leveraging them, but if you haven't looked at Django's signaling capabilities, it seems like they would be a prime candidate for this kind of activity (and more appropriate than global variables).
https://docs.djangoproject.com/en/dev/ref/signals/

Creating an in memory constant when django starts

I have this kind of setup :
Overridden BaseRunserverCommand that adds another option (--token) that would get a string token.
Store it in the app called "vault" as a global variable
Then continue executing the BaseRunserverCommand
Now later when I try to get the value of this global variable after the server started, I am unable to see the value. Is this going out of scope? How to store this one time token that is entered before the django starts?
Judging by the name of the command line option, this sounds like a configuration variable -- why not put it in settings.py like all the other configurations?
If it's a secure value that you don't want checked in to version control, one pattern I've seen is to put secure or environment-sensitive (i.e. only makes sense in production or development) configurations in a local_settings.py file which is not checked in to version control, then add to the end of your settings.py:
try:
from local_settings import *
except ImportError:
# if you require a local_settings to be present,
# you could let this exception rise, or raise a
# more specific exception here
pass
(Note that some people like to invert the import relationship and then use --settings on the command line with runserver -- this works, too, but requires that you always remember to use --settings.)
There's no such thing as a "global variable" in Python that is available from everywhere. You need to import all names before you can use them.
Even if you did this, though, it wouldn't actually work on production. Not only is there no command that you run to start up the production server (it's done automatically by Apache or whatever server software you're using), the server usually runs in multiple processes, so the variable would have to be set in each of them.
You should use a setting, as dcrosta suggests.

Categories

Resources