How can one instrospect to receive the current thread object?
Consider this somewhat artificial code snippet. The use case is different, but for the sake of simplicity, I've boiled it down the the essential bit
t1 = threading.Thread(target=func)
t2 = threading.Thread(target=func)
marked_thread_for_cancellation = t1
t1.start()
t2.start()
def func():
if [get_thread_obj] is marked_thread_for_cancellation: # <== introspect here
return
# do something
You can use thread.get_ident function. Compare thread.get_ident() with Thread.ident as follow:
import thread
import threading
import time
marked_thread_for_cancellation = None
def func(identifier):
while threading.get_ident() != marked_thread_for_cancellation:
time.sleep(1)
print('{} is alive'.format(identifier))
print('{} is dead'.format(identifier))
t1 = threading.Thread(target=func, args=(1,))
t2 = threading.Thread(target=func, args=(2,))
t1.start()
t2.start()
time.sleep(2)
marked_thread_for_cancellation = t1.ident # Stop t1
In Python 3, use threading.get_ident.
You can also use your own identifier instead of thread.get_ident:
import threading
import time
marked_thread_for_cancellation = None
def func(identifier):
while identifier != marked_thread_for_cancellation:
time.sleep(1)
print('{} is alive'.format(identifier))
print('{} is dead'.format(identifier))
t1 = threading.Thread(target=func, args=(1,))
t2 = threading.Thread(target=func, args=(2,))
t1.start()
t2.start()
time.sleep(2)
marked_thread_for_cancellation = 1 # Stop t1 (`1` is the identifier for t1)
To make minimal changes to your code, here is probably what you are after:
import threading
def func():
if threading.current_thread() is marked_thread_for_cancellation: # <== introspect here
print 'cancel'
else:
print 'otherwise'
t1 = threading.Thread(target=func)
t2 = threading.Thread(target=func)
marked_thread_for_cancellation = t1
t1.start()
t2.start()
But I do not understand what do you mean by introspection. marked_thread_for_cancellation is shared by all threads, all threads have by their own is some local data, accessible via threading.local().
Related
Hi I am trying to make it so 2 threads will change the other one but I can't figure it out this is an example of what I have
Import time
Import threading
s=0
def thing1():
time.sleep(1)
s+=1
def thing2():
print(s)
t = threading.Thread(target = thing1)
t.start()
t2 = threading.Thread(target = thing2)
t2.start()
When they run thing2 will print 0, not the seconds. I have it so they run later this is just all the code that's necessary
You need to use a semaphore so that each thread is not accessing the variable at the same time. However, any two threads can access the same variable s using global.
import threading
import time
s = 0
sem = threading.Semaphore()
def thing1():
global s
for _ in range(3):
time.sleep(1)
sem.acquire()
s += 1
sem.release()
def thing2():
global s
for _ in range(3):
time.sleep(1)
sem.acquire()
print(s)
sem.release()
t = threading.Thread(target = thing1)
t.start()
t2 = threading.Thread(target = thing2)
t2.start()
I can't seem to bring multithreading to work.
I simplified my problem and I still can't get my threads to print properly (so I guess they're not executing correctly).
import time, threading
s_print_lock = threading.Lock()
def s_print(*a, **b):
with s_print_lock:
print(*a, **b)
# Thread safe print function
def a():
while True:
s_print('\'a\' is running')
time.sleep(5)
# Thread 1
def b():
while True:
s_print('\'b\' is running')
time.sleep(5)
# Thread 2
if __name__ == "__main__":
t1 = threading.Thread(target=a())
t2 = threading.Thread(target=b())
t1.start()
t2.start()
And the output is:
'a' is running
'a' is running
'a' is running
'a' is running
...
The target must be a callable. You are executing a() so it's getting in the while True loop and never ending, so never starting the thread. Try this:
if __name__ == "__main__":
t1 = threading.Thread(target=a)
t2 = threading.Thread(target=b)
t1.start()
t2.start()
I am trying to use while loops inside threads for a bigger project. For simplicity I created an easier example to test it, but it doesn`t work.
My goal is to control the thread for the main function and when the variable go_thread_one is switched to False the thread should end. At the moment the second thread is not being used and only the first thread print its text.
How can I fix this error?
Below is the simplified version of my code:
import time
from threading import Thread
go_thread_one = True
def first_thread():
while go_thread_one:
print('Thread 1')
time.sleep(0.5)
def second_thread():
print('Thread 2')
if __name__ == "__main__":
t1 = Thread(target=first_thread())
t2 = Thread(target=second_thread())
t1.daemon = True
t2.daemon = True
t1.start()
t2.start()
time.sleep(2)
go_thread_one = False
print("end main Thread")
First of all, there is a problem in these lines:
t1 = Thread(target=first_thread())
t2 = Thread(target=second_thread())
You should pass a callable object to the Thread, but instead you call a function and pass its result. So you don't even create a t1, but go inside first_thread function and loop there forever.
To fix this, change Thread creation to:
t1 = Thread(target=first_thread)
t2 = Thread(target=second_thread)
Next, the
go_thread_one = False
will not give a desired effect – main thread will finish after time.sleep(2) even without this line.
To deal with it, you can add
t1.join()
t2.join()
I want to pause the execution of t1 (thread_A) until the t2 (thread_B) complete its execution.
import threading
import time
def thread_A():
for x in range(50):
print(x)
time.sleep(0.5)
def thread_B():
for x in range(5):
print(x)
time.sleep(0.5)
if __name__ == "__main__":
t1 = threading.Thread(target=thread_A)
t1.start()
t2 = threading.Thread(target=thread_B)
t2.start()
For example, the simplest way:
...
t2 = threading.Thread(target=thread_B)
t2.start()
t2.join() # wait t2 finished
t1 = threading.Thread(target=thread_A)
t1.start()
t1.join() # wait t1 finished
As I know there is no special method to pause a thread. These should be somehow synchronized. For example, using threading.Event object:
import threading
import time
event = threading.Event()
def thread_A():
event.wait()
for x in range(50):
print(x)
time.sleep(0.5)
def thread_B():
for x in range(5):
print(x)
time.sleep(0.5)
event.set()
if __name__ == "__main__":
t1 = threading.Thread(target=thread_A)
t1.start()
t2 = threading.Thread(target=thread_B)
t2.start()
python code:
import threading
def f1():
#long looping
def f2():
#another long looping
t1 = threading.Thread(target=f1)
t2 = threading.Thread(target=f2)
t1.start()
t2.start()
#t2.join(t1) <---???
Is that possible in main thread to call something like t2.join(t1)?
Understanding that I can call t2.join() from f1(), but I am seeking an way calling from external(not in t1 and t2).
Thank you.
No, you cant specify a thread in the join method.
If you want to wait for both t1 and t2 to complete before continuing execution in the main thread, join both threads:
import threading
import time
def f1():
#long looping
def f2():
#another long looping
t1 = threading.Thread(target=f1)
t2 = threading.Thread(target=f2)
t1.start()
t2.start()
t1.join()
t2.join()
print("Continuing with main thread...")