Search code examples
pythonfunctionmultiprocessingglobal-variableslocal-variables

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


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 Giriniz\n")
    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))

Solution

  • 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]