changing variable between flask server and a multiprocessing
<p>I have a flask server running and multiprocessing running a loop working. I need to be able to change a variable in the flask server and have it to be used in an <code>if</code> statement in the loop. Here is my code, I removed a lot of things that I thought was not important to show.</p>

<p>The variable that needs to be changed is <code>toggle</code> (only needs to be <code>1</code> or <code>0</code>)
It gets changed in <code>sms()</code> and used with an <code>if</code> statement in the loop.</p>

<pre><code># I removed a lot of stuff that I don't think was needed 

import time
import math
from pyicloud import PyiCloudService
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()
from math import sin, cos, sqrt, atan2, radians
from twilio.rest import TwilioRestClient 
from multiprocessing import Process, Value
from flask import Flask, request
from twilio import twiml
import os
#os.system('clear')

app = Flask(__name__)

sent = 0 #only needed for loop

toggle = 0 # this is the variable that needs to be changed and viewed



def distance(x):
    #returns distance in miles or km

@app.route('/sms', methods=['POST'])
def sms():
    global toggle

    #command replies
    error = 'You did not enter a valid command'
    on = 'Automatic tracker has been turned on.'
    already_on = 'The automatic tracker is already on.'
    off = 'Automatic tracker has been turned off.'
    already_off = 'The automatic tracker is already off.'
    toggle_error = 'There was a changing the status automatic tracker.'
    status0 = 'The automatic tracker is currently off.'
    status1 = 'The automatic tracker is currently on.'
    status_error = 'There was a error checking the status of the automatic tracker.'

    message_body = request.form['Body'] # message you get when sending a text to twilio number ex. I send "On" to the number and message_body will = "On"
    resp = twiml.Response() # what twilio will send back to your number

    if message_body == "on" or message_body == "On": #turn on automatic tracker
        if toggle == 0: #set toggle to 1
            toggle = 1
            resp.message(on)
            print on
            time.sleep(3)
        elif toggle == 1: #say toggle is on
            resp.message(already_on)
            print already_on
            time.sleep(3)
        else: #say toggle_error
            resp.message(toggle_error)
            print toggle_error
            time.sleep(3)
    elif message_body == "off" or message_body == "Off": #turn off automatic tracker
        if toggle == 1: #set toggle to 0
            toggle = 0
            resp.message(off)
            print off
            time.sleep(3)
        elif toggle == 0: #say toggle is off
            resp.message(already_off)
            print already_off
            time.sleep(3)
        else: #say toggle_error
            resp.message(toggle_error)
            print toggle_error
            time.sleep(3)
    elif message_body == "status" or message_body == "Status": #return status of automatic tracker
        if toggle == 1: #say toggle is on
            resp.message(status1)
            print status1
            time.sleep(3)
        elif toggle == 0: #say toggle is off
            resp.message(status0)
            print status0
            time.sleep(3)
        else: #say status_error
            resp.message(status_error)
            print status_error
            time.sleep(3)
    else: #say invalid command
        resp.message(error)
        print error
        print " "
        time.sleep(3)
    return str(resp)
    print " "

def record_loop(loop_on):
    while True:
        global sent
        global toggle
        if toggle == 1: #toggle does not read as 1 when changed in sms()
            if distance(2) &lt; 2.5:
                if sent == 0:
                    print "CLOSE"
                    print "sending message"
                    print distance(2)
                    client.messages.create(
                    to="phone number to send to", #I removed the 2 numbers
                    from_="twillio number", #I removed the 2 numbers
                    body= "CLOSE!", 
                    )
                    sent = 1
                else:
                    print "CLOSE"
                    print "not sending"
                    print distance(2)
            else:
                print "not close"
                print distance(2)
                sent = 0
        else:
            print 'toggle is off'
            print toggle
        time.sleep(1)
        print " "
        time.sleep(20)

if __name__ == "__main__":
   recording_on = Value('b', True)
   p = Process(target=record_loop, args=(recording_on,))
   p.start()  
   app.run(use_reloader=False)
   p.join()
</code></pre>

<p>Multiprocessing efectivelly runs the target function in another process - which also means that is an entirely new Python program - this otherprogram won't share any variables with the parent program. That is why your use of a global variable to communicate with your secondary loop won't work in this way: the <code>toggle</code> variable available inside your <code>record_loop</code> is independent of the one used by the program's views.</p>

<p>In a well formed application, all you'd need is to use an instance of <a href="https://docs.python.org/2/library/multiprocessing.html#exchanging-objects-between-processes" rel="nofollow"><code>multiprocessing.Queue</code></a> to communicate values to code running in a function in another process. </p>

<p>However, "weel behaved" is not what you have there - the use of a multiprocessign.Queue assumes the originating process always has access to the one Queue object that is shared with the sub-process. However, you are using a Flask application, which in turn uses the WSGI Python model - which in turn makes mandatoy that each HTTP request processing (that is, each call to your <code>sms</code> view function) is independent of all other resources in the code - inclusing global variables. That is because in a WSGI server context, each HTTP request could be served by a different proces entirely (that will vary with teh WSGI server configuration).</p>

<p>So, for "real world"  cases of HTTP requests that trigger a longer process on the server side, one of the best approaches is to use <a href="http://www.celeryproject.org/" rel="nofollow">Celery</a>. With Celery, you explicitly start your workers, that exist independent of the processes used to answer HTTP requests (even if both the view and worker code lies on the same <code>.py</code> file). Your views will call functions in the worker in a transparent way, and they will simply execute in asynchronously in another process.</p>

<p>The multiprocessing approach with <code>Queue</code> can be used, however, if you don't mind have several processes running your <code>record_loop</code> code in parallel, without one knowing anything about the other - since you are just triggering remote API's on this code, it looks like it would not be a problem.</p>

python flask python-multiprocessing