Django view alter global variable - python

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/

Related

How to properly finalize/cleanup pythonnet CLR objects?

I'm using python to communicate with a certain piece of software through the provided API. As the API-code is written in C#, I use pythonnet to import the DLL and subsequently use it. It is beneficial to do so using e.g. Jupyter Lab or Jupyter Notebook when optimizing the code, as you can easily compare the results within your code and within the software. However, I run into an issue with cleanup. The API requires you to establish connection by running the following code
import clr
clr.AddReference('API')
api = __import__('API', globals(), locals(), [], 0)
connection = api.connection()
app = connection.connect()
Now you can communicate with the software using app. The main reason for my issue it that you are only allowed to have one app in the CLR. If you want to create a new one, you should call app.close() and subsequently newapp = connection.connect(). What happens when you create newapp without calling app.close() is not clearly defined. I'm unsure how C# would handle this, would it overwrite the app in memory, would app now also point to newapp, or something else? With that, I'm even more unsure how python+CLR handles it.
To ensure that your would always work with a properly connected app, I have created a class that only allows one instance of app to be present. This restriction is implemented by evaluating connection.Alive through the API, which is True when an app is spawned and not properly closed yet. The class is similar to:
class APIWrapper:
def __init__(self, api):
self.API = api
self.Connection = api.connection()
def connect():
if self.Connection.Alive:
raise RunTimeError('Only one live application is allowed at runtime')
app = self.Connection.connect()
return app
While this works fine, my issue arises when I accidentally do something like:
wrap = APIWrapper()
wrap.connect()
When doing so, the app goes live and wrap.Connection.Alive evaluates to True. However, as I do not assign the return of wrap.connect() to a variable, I cannot close it using app.close(). For example, if I do:
wrap = APIWrapper()
print(wrap.Connection.Alive) # -> False
app = wrap.connect()
print(wrap.Connection.Alive) # -> True
app.close()
print(wrap.Connection.Alive) # -> False
wrap.connect()
print(wrap.Connection.Alive) # -> True
I cannot close the connection anymore. I have thought about altering the class so the to just bind wrap.connect() to wrap.App and allow access through the attribute. This would solve the problem of losing the app, but I prefer to not have to call wrap.App continuously for code readability. Additionally, I am just wondering if there is a proper way of handling these finalization problems?
First of all, if calling wrap.connect() without storing the return value anywhere is the problem, then there is an easy solution for it: don't do it! It looks like the connection is a resource, so you must keep track of it to release it properly when the time comes.
In your example, what should happen to the previously created connection, when somebody calls connect() again?
Second, in Python there are two ways to explicitly keep track of resources:
with statements + context managers (highly recommended). In this case you would need to implement a context manager on your wrappers.
__del__ function, that you can define, that will be called when the object is no longer needed. This one you should avoid, because it will execute at arbitrary time, meaning when you try to create a new connection, the old one might still be around, because Python did not realize it should call __del__ yet.
Another alternative is to make a singleton.

Using a shared variable between routes and main in flask

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

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 : Call a method only once when the django starts up

I want to initialize some variables (from the database) when Django starts.
I am able to get the data from the database but the problem is how should I call the initialize method . And this should be only called once.
Tried looking in other Pages, but couldn't find an answer to it.
The code currently looks something like this ::
def get_latest_dbx(request, ....):
#get the data from database
def get_latest_x(request):
get_latest_dbx(request,x,...)
def startup(request):
get_latest_x(request)
Some people suggest( Execute code when Django starts ONCE only? ) call that initialization in the top-level urls.py(which looks unusual, for urls.py is supposed to handle url pattern). There is another workaround by writing a middleware: Where to put Django startup code?
But I believe most of people are waiting for the ticket to be solved.
UPDATE:
Since the OP has updated the question, it seems the middleware way may be better, for he actually needs a request object in startup. All startup codes could be put in a custom middleware's process_request method, where request object is available in the first argument. After these startup codes execute, some flag may be set to avoid rerunning them later(raising MiddlewareNotUsed exception only works in __init__, which doesn't receive a request argument).
BTW, OP's requirement looks a bit weird. On one hand, he needs to initialize some variables when Django starts, on the other hand, he need request object in the initialization. But when Django starts, there may be no incoming request at all. Even if there is one, it doesn't make much sense. I guess what he actually needs may be doing some initialization for each session or user.
there are some cheats for this. The general solution is trying to include the initial code in some special places, so that when the server starts up, it will run those files and also run the code.
Have you ever tried to put print 'haha' in the settings.py files :) ?
Note: be aware that settings.py runs twice during start-up

mod_python caching of variables

I'm using mod_python to run Trac in Apache. I'm developing a plugin and am not sure how global variables are stored/cached.
I am new to python and have googled the subject and found that mod_python caches python modules (I think). However, I would expect that cache to be reset when the web service is restarted, but it doesn't appear to be. I'm saying this becasue I have a global variable that is a list, I test the list to see if a value exists and if it doesn't then I add it. The first time I ran this, it added three entries to the list. Subsequently, the list has three entries from the start.
For example:
globalList = []
class globalTest:
def addToTheList(itemToAdd):
print(len(globalTest))
if itemToAdd not in globalList:
globalList.append(itemToAdd)
def doSomething():
addToTheList("I am new entry one")
addToTheList("I am new entry two")
addToTheList("I am new entry three")
The code above is just an example of what I'm doing, not the actual code ;-). But essentially the doSomething() method is called by Trac. The first time it ran, it added all three entries. Now - even after restarting the web server the len(globalList) command is always 3.
I suspect the answer may be that my session (and therefore the global variable) is being cached because Trac is remembering my login details when I refresh the page in Trac after the web server restart. If that's the case - how do I force the cache to be cleared. Note that I don't want to reset the globalList variable manually i.e. globalList.length = 0
Can anyone offer any insight as to what is happening?
Thank you
Obligatory:
Switch to wsgi using mod_wsgi.
Don't use mod_python.
There is Help available for configuring mod_wsgi with trac.
read the mod-python faq it says
Global objects live inside mod_python
for the life of the apache process,
which in general is much longer than
the life of a single request. This
means if you expect a global variable
to be initialised every time you will
be surprised....
go to link
http://www.modpython.org/FAQ/faqw.py?req=show&file=faq03.005.htp
so question is why you want to use global variable?

Categories

Resources