All the examples I've been able to get to don't really address my problem, of having a certain procedure in the background constantly looping, while the rest of the program continues.
Here is a simple example of a method that works, using _thread:
import _thread
import time
def countSeconds():
time.sleep(1)
print("Second")
_thread.start_new(countSeconds, ())
def countTenSeconds():
time.sleep(10)
print("Ten seconds passed")
_thread.start_new(countTenSeconds, ())
_thread.start_new(countSeconds, ())
_thread.start_new(countTenSeconds, ())
Ignoring the obvious fact that we could track the seconds, and just print something different if it's a multiple of ten, how would I go about creating this more efficiently.
In my actual program, the threading seems to be guzzling RAM, I assume from creating multiple instance of the thread. Do I have to "start_new" thread at the end of each procedure?
Thanks for any help.
All the examples I've been able to get to don't really address my problem
Which examples?
This does work for me.
import threading
def f():
import time
time.sleep(1)
print "Function out!"
t1 = threading.Thread(target=f)
print "Starting thread"
t1.start()
time.sleep(0.1)
print "Something done"
t1.join()
print "Thread Done"
You're asking for a repeated thread, I don't get what exactly you need, this might work:
import threading
var = False
def f():
import time
counter = 0
while var:
time.sleep(0.1)
print "Function {} run!".format(counter)
counter+=1
t1 = threading.Thread(target=f)
print "Starting thread"
var = True
t1.start()
time.sleep(3)
print "Something done"
var = False
t1.join()
print "Thread Done"
use the threading.timer to continue launching a new background thread
import threading
import time
def countSeconds():
print("Second")
threading.Timer(1, countSeconds).start()
def countTenSeconds():
print("Ten seconds passed")
threading.Timer(10, countTenSeconds).start()
threading.Timer(1, countSeconds).start()
threading.Timer(10, countTenSeconds).start()
Related
This question already has answers here:
Is there any way to kill a Thread?
(31 answers)
Closed 3 years ago.
To simplify the situation I'm having: I'm trying to terminate a thread while it is still running in Python 2.7, and I'm not sure how to do it.
Take this simple code:
import time
import threading
def thread1():
print "Starting thread 1"
while True:
time.sleep(0.5)
print "Working"
thread1 = threading.Thread(target=thread1, args=())
thread1.start()
time.sleep(2)
print "Killing thread 1"
thread2.stop()
print "Checking if it worked:"
print "Thread is: " + str(thread1.isAlive())
Thread 1 keeps on 'working' and I'm trying to kill it in the main thread. Any idea on how to do it? I've tried:
threat1.terminate
threat1.stop
threat1.quit
threat1.end
This all seems to point that there is no way to really stop it with a simple line of code. What could you suggest?
To terminate an Thread controlled, using a threadsafe threading.Event():
import threading, time
def Thread_Function(running):
while running.is_set():
print('running')
time.sleep(1)
if __name__ == '__main__':
running = threading.Event()
running.set()
thread = threading.Thread(target=Thread_Function, args=(running,))
thread.start()
time.sleep(1)
print('Event running.clear()')
running.clear()
print('Wait until Thread is terminating')
thread.join()
print("EXIT __main__")
Output:
running
running
Event running.clear()
Wait until Thread is terminating
EXIT __main__
Tested with Python:3.4.2
Online Demo: reply.it
Usually, in this cases, I use some kind of signal:
import time
import threading
class thread1(threading.Thread):
def run(self):
self.kill = False
print "Starting thread 1"
while not self.kill:
time.sleep(0.5)
print "Working"
thread_obj = thread1()
thread_obj.start()
time.sleep(2)
print "Killing thread 1"
thread_obj.kill = True
print "Checking if it worked:"
time.sleep(1)
print "Thread is: " + str(thread_obj.isAlive())
EDIT
After reading the answer suggested in one of the comment... I realized that this is just a simplified version of what is described there. I hope this will be useful anyway.
Indeed!
threads cannot be destroyed, stopped, suspended, resumed, or interrupted
(So say the docs in a paragraph below the link.)
Make your threads listen to signals you may send, via a queue (best), a shared variable (worse), or any other means. Be careful and don't let them run unchecked loops, as in your example code.
I'm trying to stop the code from running if the user presses ctrl+shift+c. I use the code below. Unfortunately sys.exit() stops only "wait_for_ctrl_shift_c" function, but not "main_func". What should I use to stop them both?
Thanks.
def wait_for_ctrl_shift_c():
print ('wait_for_ctrl_shift_c is working')
keyboard.wait('ctrl+shift+c')
print('wait_for_ctrl_shift_c was pressed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
sys.exit()
def main_func():
a=0
while True:
print ('Working2 ',a)
a=a+1
sleep(1)
if __name__ == '__main__':
Thread(target = wait_for_ctrl_shift_c).start()
Thread(target = main_func).start()
There are multiple ways to do it. First of all you have 3 threads, one main thread and the other 2 (infinite loop & keyboard one) you create.
You can register signals and handle it, also you can call interrupt_main to interrupt main thread (not the while loop thread). Interrupt will go to main exception handler. Also instead of True i changed the second thread to have an attribute to check if it should run for clean exit.
import os
import threading
import time
import sys
import _thread
def wait_for_ctrl_shift_c():
print ('wait_for_ctrl_shift_c is working')
keyboard.wait('ctrl+shift+c')
print ('exiting thread')
_thread.interrupt_main()
sys.exit()
def main_func():
a=0
t = threading.currentThread()
while getattr(t, "run", True):
print ('Working2 ',a)
a=a+1
time.sleep(1)
print ('exiting main_func')
if __name__ == '__main__':
try:
t1 = threading.Thread(target = wait_for_ctrl_shift_c)
t2 = threading.Thread(target = main_func)
t1.start()
t2.start()
t1.join()
t2.join()
except:
print ('main exiting')
t2.run = False
sys.exit()
Open shell in another window, type ps to list running processes, and kill the Python one (via kill 3145, if 3145 is its PID) to stop them both. This way we kill the process within which these threads run.
I want to run a function every few seconds in Python. The function execution takes some time, and I want to include that in the waiting time as well.
I don't want to do this, because it is not strictly executed every 2 seconds and will break the periodicity (my_function also takes time to execute.)
while True:
time.sleep(2)
my_function()
I don't want to do this neither, because it uses too much CPU on the while loop of Thread-2.
# Thread-1
While True:
time.sleep(2)
event.set()
# Thread-2
While True:
if event.is_set():
my_function()
else:
pass
Can anyone please help me?
You can consider ischedule. It takes care of the function execution time right out the box, and doesn't waste CPU time for busy waiting. You can use:
from ischedule import schedule, run_loop
schedule(my_function, interval=2)
run_loop()
I believe the schedule module is your friend
I found this code works pretty well, if I understood your question correctly.
Code broken down:
runs func1
runs func2
waits 2s
does something else after that
waits 1s
does it all again
import threading
import time
def func1():
print("function 1 has been called")
def func2():
print("function 2 has been called")
def loop():
print("loop print 1")
thread = threading.Thread(target=func1, name="thread")
thread.start()
while thread.is_alive():
continue
if not thread.is_alive():
thread2 = threading.Thread(target=func2, name="thread2")
thread2.start()
while thread2.is_alive():
continue
time.sleep(2)
while True:
loop()
print("Some other thing")
time.sleep(1)
I have thrown together a quick threading test:
import threading
def test():
print "it don't work"
while True:
threading.Timer(1, test).start()
It runs test, but it doesn't wait. What's wrong?
In each loop iteration, you start a new thread. Therefore you will reach the limit of allowed thread and you will get an exception : can't start new thread.
while True:
threading.Timer(1, test).start()
You can add global flag and wait until the function is executed - You should use time.sleep to avoid busy waiting.
a = False
def test():
global a
print("hallo")
a = True
threading.Timer(10, test).start()
while not a:
time.sleep(1)
print('done')
I'm very much a beginner in both python and programming. Trying to get multithreading work but haven't managed so far. Grateful for any help or tips.
from threading import Thread
import time
import requests
class crawler:
def get_urls(self):
while True:
#r = self.s.get('http:\\someurl')
time.sleep(1)
print 'Thread 1'
def thread_test(self):
while True:
print 'Thread 2'
time.sleep(1)
crawl = crawler()
if __name__ == '__main__':
Thread(target=crawl.get_urls()).start()
Thread(target=crawl.thread_test()).start()
It has been a while since i have done thread programming in python but I remembered that you will have to call .join() on each thread or else the main thread will exit before your spawn thread get a chance to execute.
T1 = Thread(target=crawl.get_urls()).start()
T2 = Thread(target=crawl.thread_test()).start()
T1.join()
T2.join()
should do the trick
edit I just looked into python threading library the issue is that target is expecting a callable object. when you call target=crawl.get_urls() the method was being evaluated rather than passing the method.
from threading import Thread
import time
import requests
class crawler:
def get_urls(self):
while True:
#r = self.s.get('http:\\someurl')
time.sleep(1)
print 'Thread 1'
def thread_test(self):
while True:
print 'Thread 2'
time.sleep(1)
crawl = crawler()
if __name__ == '__main__':
Thread(target=crawl.get_urls).start()
Thread(target=crawl.thread_test).start()
ref: https://docs.python.org/3/library/threading.html#threading.Thread