Search code examples
pythonglobalpython-multithreadingosc

Python global variable shared between threads (using python-osc)


I'm stuck with a threading problem here. I need threads to access a global variable.

I've read a previous answer to a similar question and I understood the "power" of the global keyword in order for functions and threads to access to global variables.

I'm able to make the following code work and it is pretty straightforward to me:

# WORKING CODE !!!

from threading import Thread
import sys, time

a = "" #global variable

def thread1(threadname):
    global a
    while True:
        a *= 2
        time.sleep(2)

def thread2(threadname):
    global a
    while True:
        a += 1
        time.sleep(1)

if __name__ == "__main__":
    thread1 = Thread( target=thread1, args=("Thread-1", ) )
    thread2 = Thread( target=thread2, args=("Thread-2", ) )

    a = 23

    thread1.start()
    thread2.start()

    while True:
        print(a)

Now I would like to have an OSC driven function to modify the global variable a. I'm using the python-osc module and I'm making the OSC server running on its own thread. As before I have declared a as a global variable inside the mapped function associated with the "/learn" OSC method.

Strangely to my comprehension the following code is not behaving the same way as the previous one.

edited 2018-10-18, 16:14: "a" is not increasing at all and what I'm seeing printed is

a: 1

printed continuosly. As if we had two different "a" values: one that is increasing inside the OSC thread which is different from the global "a" of the main one.

What I doing wrong?

import threading
from time import sleep
from pythonosc import osc_server, dispatcher

OSCaddress = "192.168.1.68"
OSCport    = 13000

a = ""

# OSC functions
def menageLearnButton(unused_addr, args, value):
    global a
    if value == 1:
        a += 1
    else:
        a += 3

if __name__ == "__main__":
    # OSC dispatcher to respond to incoming OSC messages
    dispatcher = dispatcher.Dispatcher()
    dispatcher.map("/learn", menageLearnButton, "learning")

    a = 1

    # better to run the OSC server on its own thread
    # in order not to block the program here
    OSCserver = osc_server.ForkingOSCUDPServer((OSCaddress, OSCport), dispatcher)
    OSCserver_thread = threading.Thread(target=OSCserver.serve_forever)
    OSCserver_thread.start()

    while True:
        print("a: {}".format(a))
        sleep(1)

Thank you very much for your support.


Solution

  • I think what is going on is that 'ForkingOSCUDPServer' is creating a new process for each OSC request so 'a' is getting reinitialized each time. If I switch your code to use 'ThreadingOSCUDPServer' it seems to have the desired behavior.