python3 - Incrementing a global variable causes bo

2019-08-20 10:32发布

问题:

I'm not sure how to phrase the question because I don't know what's causing the problem. I think incrementing the global variable is causing the problem when it's deployed to Heroku.

I have this Bot which needs to ask questions in a sequential way. I managed to make it work, it works fine when I test it on my machine. But, when the Bot is deployed to Heroku, It goes nuts and asks random questions and shows random facts without any order.

Here's how it works

question_dict = {
            'Locq0':[{'question':"Some question 0",'options':(["Continue","@continue"])}],
            'Locq1':[{'question':"Some question 1",'options':(["Continue","@continue"])}],
            'Locq2':[{'question':"Some question 2",'options':(["Continue","@continue"])}],}

The questions are inside a dict. So I made a function to loop over the dict.

def main():
   if user_payload == "@continue":
      increment()

counter = 0
def increment():
    global counter 
    if counter <= len(question_dict):
       counter += 1
       quiz(counter)

def quiz(counter):
    question = question_dict['Locq{}'.format(counter)][0]['question']
    option   = question_dict['Locq{}'.format(counter)][0]['options']
    # display the question and option
    print(question)
    print(option)

So each time I get a correct answer from the user, I increment the counter and pass the current counter value to the quiz function.

For eg:

Initial counter is set to 0. If the user clicks the continue button, the counter is incremented by 1 and passes the current counter value to the quiz() then the quiz function displays the next question.

for counter 0 => question_dict['Locq0']

for counter 1 => question_dict['Locq1']

And so on. This will take place to all the questions present in a dict.

All of this works fine when I test it on my machine. But when the bot is deployed to heroku, I don't know what happens to the counter, It shows random questions from the dict. I also set a debug text to show me the counters value and It changes all the time. Sometimes the value is 1 and the next value is 3 or 4 or 0 or it repeats itself.

Counter is a global variable and I think that's causing the problem on heroku. Anyone knows what's wrong with this or why it's doing it?

回答1:

Quick answer : HTTP is a stateless protocol, so you must either pass the whole state in your http request or store the state in a server-side "session" mechanism.

Longer answer: web apps are typically served by a multiprocess front web server, which means you will have N (isolated) processes handling incoming HTTP requests. Which one will serve which request is totally unpredictable. IOW you cannot rely on globals (which are pre-process) to keep state between requests.

The first solution is to use sessions instead of globals (there are quite a few ways to to so with flask so google for "flask session" and choose whatever you like)

The other solution is to pass the next quizz id to your template so it can be submitted with the form or as part of the url (either in the url path or querystring).