Passing variable changes between threads in Python functions [Beginner] - python

So I have this code:
import time
import threading
bar = False
def foo():
while True:
if bar == True:
print "Success!"
else:
print "Not yet!"
time.sleep(1)
def example():
while True:
time.sleep(5)
bar = True
t1 = threading.Thread(target=foo)
t1.start()
t2 = threading.Thread(target=example)
t2.start()
I'm trying to understand why I can't get bar to = to true.. If so, then the other thread should see the change and write Success!

bar is a global variable. You should put global bar inside example():
def example():
global bar
while True:
time.sleep(5)
bar = True
When reading a variable, it is first searched inside the function and if not found, outside. That's why it's not necessary to put global bar inside foo().
When a variable is assigned a value, it is done locally inside the function unless the global statement has been used. That's why it's necessary to put global bar inside example()

You must specify 'bar' as global variable. Otherwise 'bar' is only considered as a local variable.
def example():
global bar
while True:
time.sleep(5)
bar = True

Related

Cache in python function not using global keyword

I am trying to create a cache array that my function can modify and access multiple times.
I can achieve this the ugly way:
def func():
global cache
try: cache
except NameError: cache = {"stuff"}
### does stuff with cache
...
but I can't do this with the nonlocal keyword, I would really like to know why...
UPDATE: user #quamrana asked for an example:
def main():
def func1():
global x
x = 3.14
def func2():
nonlocal y
y = 3.14
func1()
print(x)
func2()
print(y)
If __name__ == "__main__":
main()
I can also pass an outside variable to the function and use it with some methods, but I would like to avoid creating one manually:
def func(cache):
cache.update({"stuff": 42})
my_stuff = cache.get("stuff")
def main():
func_cache = {}
func(func_cache)
if __name__ == "__main__":
main()
are there good ways to do this kind of thing?

How to keep executing code until another function returns value?

from time import sleep
def foo():
sleep(3)
return True
while True:
print('Running')
if foo() == True:
print('Finished.')
break
I want to keep printing "Running" but when foo returns True I want to print "Finished" (once) and break out of the loop.
I have tried the above but it prints "Running" just once and waits for foo to finish executing and then continues.
import threading
from time import sleep
flag = True
def foo()->None:
global flag
sleep(1)
flag = False
if __name__ == "__main__":
t1 = threading.Thread(target=foo)
t1.start()
while flag:
print('Running')
print('Finished')
Because you worked with only one thread, when you call the function the main stops until the function returns.
Therefore, if you want the main code and the function to run together, you have to work with threads.
So, after trying somethings I found 2 solutions, of my own question, that uses threading.
1. Modifies the foo function
from time import sleep
from threading import Thread
x = True
def foo():
sleep(3)
global x
x = False
print('finished')
def printing():
while x:
print('Running')
foo_thread = Thread(target=foo)
foo_thread.start()
printing_thread = Thread(target=printing)
printing_thread.start()
2. Uses decorator to keep foo unchanged
from time import sleep
from threading import Thread
x = True
def sets_true(func):
def wrapper():
returned_value = func()
global x
x = False
print('finished')
return wrapper
#sets_true
def foo():
sleep(3)
return True
def printing():
while x:
print('Running')
foo_thread = Thread(target=foo)
foo_thread.start()
printing_thread = Thread(target=printing)
printing_thread.start()

Change global variable in threading

I am working with threading and multiprocessing and encounter an issue, here is my code:
xxx = []
def func1(*args):
#do something 1
global list
xxx.append('x')
def func2(*args2):
func1x = partial(func1, ...(*argsx)...)
with multiprocessing.Pool(3) as pool: pool.map(func1x, arg)
def func3(arg3):
While True:
try:
# do something 2
global list
print(list)
except:
continue
def main():
t1 = threading.Thread(target=func2, args=(*args2))
t2 = threading.Thread(target=func3, args=(args3))
t1.start()
t2.start()
main()
My code block run smoothly without any error with these nested multiprocessing and threading.
Problem is eventhough I tried to set a new global variable for xxx in func1(), the print command in func3() still print [] instead of ['x'] as I expected.
I use while loop to wait for the func1() to declares new variable of xxx, still not working.
How can I use new global variable everytime it's changed in a running thread?

Why the thread does not stops?

The thread started in the start_thread method does not stop. Why ?
import time
import threading
cont_running = True
def start_thread():
threading.Thread(target=run).start()
def stop_thread():
cont_running = False
def run():
while cont_running:
print 'Thread running : ' + str(cont_running)
time.sleep(0.2)
print 'Thread ended'
start_thread()
time.sleep(2)
stop_thread()
In stop_thread(), your assignment statement creates a local variable named cont_running. This local variable is unrelated to the global variable of the same name.
Try this:
def stop_thread():
global cont_running
cont_running = False

Python - Polling a variable

I change a global variable in a signal handler and poll for it in the main program. But the value does not change in the main thread.
Is there a qualifier that I need to use to make it a volatile (like in Java) variable?
Here's the program:
test.py
import time
import signal
def debug():
closeSession = False
def sigint_handler(signal, frame):
global closeSession
print('Breaking the poll...')
closeSession=True
signal.signal(signal.SIGINT, sigint_handler)
# Start a program...
while not closeSession:
time.sleep(1)
print('Polling... closeSession = %r' % closeSession)
print('Exiting! Bye.')
# Sent 'quit' to stdin of the program
if __name__ == "__main__":
debug()
sigint_handler() gets called whenever I press Ctrl + C but the new value of closeSession is not used in the main thread.
I get the following output:
$ python test.py Polling... closeSession = False Polling...
closeSession = False
I press Ctrl + C
^CBreaking the poll... Polling... closeSession = False
Press Ctrl + C, again
^CBreaking the poll... Polling... closeSession = False
Press Ctrl + C, again
^CBreaking the poll... Polling... closeSession = False
Polling... closeSession = False
The problem is scope.
Inside the debug() function, you didn't declare closeSession as a global, which means that you have two variables called closeSession. One global and one scoped within the debug() function. And inside the sigint_handler() function, you've explicitly instructed to use global one, which is shadowed by the scoped one in the outer function.
You can solve this by declaring global before assignment in debug():
def debug():
global closeSession
closeSession = False
...
By the way, your code does not work on windows, it throws a IOError because the sleep function is interrupted. A workaround that worked for me is:
...
while not closeSession:
try:
time.sleep(1)
except IOError:
pass
print('Polling... closeSession = %r' % closeSession)
...
It's not pretty but it works.
You have to set global closeSession before accessing the variable, else you're creating a local variable with the same name and the loop will never end.
Try this:
import time
import signal
def debug():
global closeSession # <-- this was missing
closeSession = False
def sigint_handler(signal, frame):
global closeSession
print('Breaking the poll...')
closeSession=True
signal.signal(signal.SIGINT, sigint_handler)
# Start a program...
while not closeSession:
time.sleep(1)
print('Polling... closeSession = %r' % closeSession)
print('Exiting! Bye.')
# Sent 'quit' to stdin of the program
if __name__ == "__main__":
debug()

Categories