Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing a global variable from outside in a Flask based Python web application

I do not understand how to change a global variable when using the flask extension flask-script. To demonstrate my problem I developed the following small flask application, which will increase a global counter variable for every request call. In addition it offers a reset function to reset the global counter:

# -*- coding: utf-8 -*-

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

from flask import Flask
from flask.ext.script import Manager
app = Flask(__name__)
app.debug = True

manager = Manager(app)

counter = 0

@manager.command
@app.route("/reset")
def reset():
    global counter
    print "Counter before reset:", counter
    counter = 0
    print "Counter after reset:", counter
    return str(counter) 

@app.route("/")
def add():
    global counter
    print "Counter before adding:", counter
    counter +=1
    print "Counter after adding:", counter
    return str(counter)

if __name__ == "__main__":
    manager.run()       

I start my flask application using python counter.py runserver

When I access the address 127.0.0.1:5000 I see the counter increasing

Counter before adding: 0
Counter after adding: 1
127.0.0.1 - - [17/Apr/2013 10:09:35] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [17/Apr/2013 10:09:35] "GET /favicon.ico HTTP/1.1" 404 -
Counter before adding: 1
Counter after adding: 2
...

When I access the address 127.0.0.1:5000/reset I see that the counter is reset

Counter before reset: 4
Counter after reset: 0
127.0.0.1 - - [17/Apr/2013 10:10:39] "GET /reset HTTP/1.1" 200 -
127.0.0.1 - - [17/Apr/2013 10:10:39] "GET /favicon.ico HTTP/1.1" 404 -

However when I try to call the reset method from the command line using the manage interface provided by the flask-script extension the global counter variable is not reset:

> python counter.py reset
Counter before reset: 0
Counter after reset: 0
0

What am I doing wrong? How can I access and manipulate a global variable using flask-script?

like image 476
asmaier Avatar asked Apr 17 '13 08:04

asmaier


People also ask

Can you use global variables in Flask?

Sessions. More often than not, what you're really trying to do, when you use global variables in Flask, is to save user entered or recorded information across different routes, while concurrently allowing for modifications to the same. As it happens, Flask has an inbuilt library for this functionality : Flask Sessions.

Are global variables thread safe in Flask?

Flask code has to be thread-safe, also called re-entrant. Local variables and parameters are always thread-safe. Instance variables, class variables, and global variables may not be thread-safe (but they might be). Nevertheless, threads and shared variables can be useful.

How do you declare a global variable in python?

Normally, when you create a variable inside a function, that variable is local, and can only be used inside that function. To create a global variable inside a function, you can use the global keyword.

Why global variables are not thread safe?

Global variables are still not thread safe because there's still no protection against most race conditions. You can still have a scenario where one worker gets a value, yields, another modifies it, yields, then the first worker also modifies it.


1 Answers

Python global variables like counter live in operating system process memory space. Each started and stopped process (application, command, etc.) gets its own pie of memory.

When you run python counter.py reset it starts a new process with its own memory space and variables. The variable reset is run against this process, not the process running the web server.

To correctly reset the variable

  • Keep variable out of process memory space (E.g. in memcached, database)

  • Create a command which calls the web server process via a special view URL using wget, curl, urllib or such and this view resets the variable inside the process memory space

like image 108
Mikko Ohtamaa Avatar answered Oct 14 '22 02:10

Mikko Ohtamaa