1

I basically need to globalise the variable DR

I've made a variable called DR and set it to 0 outside the functions. Then the functions (which determine if something is entering or exiting the room) add 1 to DR when someone goes in and takes 1 away when someone leaves.

from multiprocessing import Process, Value
import multiprocessing
DR=0

def loop_out():
    global DR
    while True:
   
        # Read the sensor data
        light2_level = ReadChannel(light2_channel)  
        light1_level = ReadChannel(light1_channel)
        # Print out results
        if light1_level>650:
            #print("Light1: {} ({}V)".format(light1_level))
            if light2_level>650:
                print ("---GOING OUT---")
                DR-=1
                print(DR)
            time.sleep(1)
   
def loop_in():
    global DR
    while True:
   
        # Read the sensor data
        light2_level = ReadChannel(light2_channel)
        light1_level = ReadChannel(light1_channel)
        if light2_level>650:
            #print("Light2 : {} ({}V)".format(light2_level))
            if light1_level>650:
                print("---GOING IN---")
                DR+=1
                print(DR)
            time.sleep(1)

#This next part executes the two functions in multi-processing
if __name__ == '__main__':
    p1=Process(target=loop_out)
    p1.start()
    p2=Process(target=loop_in)
    p2.start()

The problem is, the value of DR outside the functions remains as 0, and inside the "in" function continues to increase as people enter, and inside the "out" function continues to decrease as people leave so you receive the output below:

*someone enters"
GOING IN
People in room: 1
*someone enters"
GOING IN
People in room: 2 
*someone leaves"
GOING OuT
People in room: -1
*someone enters"
GOING IN
People in room: 3
*someone enters"
GOING OuT
People in room: -2

I need to make DR change globally so that I can act on the amount of people inside the room. I have also tried making new variables inside the functions and doing addition on them outside however, due to the multiprocessing they do not exist outside the function. I hope this makes sense, please help.

2
  • The underlying issue is that multiprocessing uses separate processes, which do not share memory. However, the solution is not necessarily a globally shared value (which is possible) but rather some shared value passed to each worker. Are you absolutely sure you want a global value? Commented Nov 30, 2020 at 10:36
  • It isn't a necessity, no. I just need it to work. Do you have any idea how I can get it working? Thank you Commented Nov 30, 2020 at 10:48

1 Answer 1

1

Use a multiprocessing.Value as argument of your functions, and protect it with a multiprocessing.Lock since it is a shared resource:

import multiprocessing
import time

# BEGIN MOCK
light1_channel = None
light2_channel = None


def ReadChannel(channel):
    from random import randint
    return randint(600, 700)
# END MOCK


def loop_out(DR, lock):
    while True:

        # Read the sensor data
        light2_level = ReadChannel(light2_channel)
        light1_level = ReadChannel(light1_channel)
        # Print out results
        if light1_level > 650:
            # print("Light1: {} ({}V)".format(light1_level))
            if light2_level > 650:
                print ("---GOING OUT---")
                lock.acquire()
                DR.value -= 1
                lock.release()
                print(DR.value)
            time.sleep(1)


def loop_in(DR, lock):
    while True:

        # Read the sensor data
        light2_level = ReadChannel(light2_channel)
        light1_level = ReadChannel(light1_channel)
        if light2_level > 650:
            # print("Light2 : {} ({}V)".format(light2_level))
            if light1_level > 650:
                print("---GOING IN---")
                lock.acquire()
                DR.value += 1
                lock.release()
                print(DR.value)
            time.sleep(1)


# This next part executes the two functions in multi-processing
if __name__ == '__main__':
    DR = multiprocessing.Value('i', 0)
    lock = multiprocessing.Lock()
    p1 = multiprocessing.Process(target=loop_out, args=(DR, lock))
    p1.start()
    p2 = multiprocessing.Process(target=loop_in, args=(DR, lock))
    p2.start()

Edit: Here is another version without Lock instance since, as mentioned in the comments by Mister Miyagi, the Value instance already has a lock included by default:

import multiprocessing
import time

# BEGIN MOCK
light1_channel = None
light2_channel = None


def ReadChannel(channel):
    from random import randint
    return randint(600, 700)
# END MOCK


def loop_out(DR):
    while True:
        # Read the sensor data
        light2_level = ReadChannel(light2_channel)
        light1_level = ReadChannel(light1_channel)
        # Print out results
        if light1_level > 650:
            # print("Light1: {} ({}V)".format(light1_level))
            if light2_level > 650:
                print ("---GOING OUT---")
                with DR.get_lock():
                    DR.value -= 1
                print(DR.value)
            time.sleep(1)


def loop_in(DR):
    while True:
        # Read the sensor data
        light2_level = ReadChannel(light2_channel)
        light1_level = ReadChannel(light1_channel)
        if light2_level > 650:
            # print("Light2 : {} ({}V)".format(light2_level))
            if light1_level > 650:
                print("---GOING IN---")
                with DR.get_lock():
                    DR.value += 1
                print(DR.value)
            time.sleep(1)


# This next part executes the two functions in multi-processing
if __name__ == '__main__':
    DR = multiprocessing.Value('i', 0)
    p1 = multiprocessing.Process(target=loop_out, args=(DR,))
    p1.start()
    p2 = multiprocessing.Process(target=loop_in, args=(DR,))
    p2.start()
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you so much! I'll try it as soon as I get home.
Well, Frodo helps Gandalf again... ;)
A multiprocessing.Value is by default already synchronised. There is not need for a separate lock.
@MisterMiyagi thank you for your remark, I edited my answer with another solution without an additional lock instance.
Haha, hobbits really are amazing creatures ;) I really cannot thank you enough, you've taken so much stress off my plate. All the best

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.