Python Multiprocessing: Variable only changes inside the function even though there is a global statement

Question:

I am trying to change a variable inside a function and access the changed one inside another function but the first function won’t change the variable globally.

what i want my code to do:
when i press the "startKey" it should turn on and start pressing "a" every 0.5 seconds.

what it does:
i explained it with comments down below

my code:

from multiprocessing.dummy import freeze_support
import time
switch = None

kofteEkmek = "guzel"
needToCheck = False 

start = time.perf_counter()

import concurrent.futures

import keyboard
from pynput.keyboard import Key, Controller

with open("config.txt", "r") as con:
    conContent = con.read()
    startKey = str(conContent[11])
    print(startKey)


def writeCon():
    with open("config.txt", "w") as con:
        con.write("startKey = " + startKey)




if startKey == ",":

    startKey = input("Lutfen Programi Calistirmak İcin Kullanacaginiz Tusu Girinizn")
    writeCon()


def check():
    global switch
    switch = False
    while True:
        while needToCheck == True:
            if keyboard.is_pressed(startKey):
                if switch == False:
                    switch = True    #doesn't change the switch variable globally
                    print(switch)
                    time.sleep(0.5)
                    continue
                if switch == True:
                    switch = False
                    print(switch)
                    time.sleep(0.7)
#switch only changes inside the functions even though there is a global statement

print("switch= ", switch) #"switch= None"


def move():
    global switch
    print("switch inside of move: ", switch)    #equals "None" always
    while True:
        while switch == True:    #switch == None so it doesn't work :C
            for _ in range(10):
                print("pressinA")
                keyboard.press("a")
                time.sleep(0.5)



needToCheck = True
if __name__ == "__main__":
    freeze_support()
    with concurrent.futures.ProcessPoolExecutor() as executor:
        
        fMove = executor.submit(move)
        fCheck = executor.submit(check)
        
        


finish = time.perf_counter()
print(round(finish-start, 2))
Asked By: oas333

||

Answers:

I’d say the local variable switch you have created inside def check() intervenes with the global one initiated to none at the top. Try removing the one in check.

Answered By: NeverAimHigh

You can try to print ids of the ‘switch’s in your code, and you can find they are different. (In other words, they don’t share memory) Global variable doesn’t work as usual in multiprocess.

And these links provide much infomation you need.

How to update global variable in python multiprocessing

Python: How to modify a global variable in a function using pprocess

multiprocessing global variable updates not returned to parent

You can replace the corresponding part of your code using the following. It should work.

def check():
    print(switch.value)
    print(id(switch))
    while True:
        while needToCheck == True:
            # global switch
            if keyboard.is_pressed(startKey):
                if switch.value == 0:
                    switch.value = 1
                    time.sleep(0.5)
                    continue
                if switch.value == 1:
                    switch.value = 0
                    time.sleep(0.7)


def move():
    # global switch
    print("switch inside of move: ", switch.value)    #equals "None" always
    while True:
        while switch.value == 1:    #switch == None so it doesn't work :C
            for _ in range(10):
                # print("pressinA")
                keyboard.press("a")
                time.sleep(0.5)
        time.sleep(0.1)
        # print(id(switch))


needToCheck = True

def running_shared():
    # consider lock if you need
    return switch.value

def set_global(args):
    global switch
    switch = args

if __name__ == "__main__":
    freeze_support()
    switch = Value('b', 0)
    print(id(switch))
    with concurrent.futures.ProcessPoolExecutor(initializer=set_global, initargs=(switch,)) as executor:
        fMove = executor.submit(move)
        fCheck = executor.submit(check)
        futures = [fMove , fCheck]
        results = [x.result() for x in futures]
Answered By: x pie