I am runing a web project.
I want to start a thread to do one job if some event happen.
Before,I always write multithreading program.Such as below
class FetchThread(threading.Thread):
def __init__(self, profile_queue):
....
def run(self):
while true:
....
But here is only one task,I don't want a thread running all the time.
I want the thread just do one thing, then quit.But I always see others write while True in Thread.run, I don't know if method 2 is a good way .Anyone can help?
1.
class FetchThread(threading.Thread):
def __init__(self, profile_queue):
....
def stop(self):
self.__running = False
def run(self):
while self.__running:
....
self.stop()
2.
class FetchThread(threading.Thread):
def __init__(self, profile_queue):
....
def run(self):
....
If you can encapsulate your entire task into a single function, you can just use the default Thread class and pass the right arguments.
def a_task(callback):
# do your task here
callback()
def some_callback():
# some way to notify that the task is completed
pass
task = Thread(target=a_task,
kwargs={'callback': some_callback})
task.start()
If your web project involves Tornado, a previous answer I provided might be of interest to you.
Put the job you want to do in a regular function and call it like so:
>>> def job_func(arg):
... do_work(arg)
>>> Thread(target=job_func, args=(arg,)).start()
Related
I am pretty new to Python and have a question about threading.
I have one function that is called pretty often. This function starts another function in a new Thread.
def calledOften(id):
t = threading.Thread(target=doit, args=(id))
t.start()
def doit(arg):
while true:
#Long running function that is using arg
When calledOften is called everytime a new Thread is created. My goal is to always terminate the last running thread --> At all times there should be only one running doit() Function.
What I tried:
How to stop a looping thread in Python?
def calledOften(id):
t = threading.Thread(target=doit, args=(id,))
t.start()
time.sleep(5)
t.do_run = False
This code (with a modified doit Function) worked for me to stop the thread after 5 seconds.
but i can not call t.do_run = False before I start the new thread... Thats pretty obvious because it is not defined...
Does somebody know how to stop the last running thread and start a new one?
Thank you ;)
I think you can decide when to terminate the execution of a thread from inside the thread by yourself. That should not be creating any problems for you. You can think of a Threading manager approach - something like below
import threading
class DoIt(threading.Thread):
def __init__(self, id, stop_flag):
super().__init__()
self.id = id
self.stop_flag = stop_flag
def run(self):
while not self.stop_flag():
pass # do something
class CalledOftenManager:
__stop_run = False
__instance = None
def _stop_flag(self):
return CalledOftenManager.__stop_run
def calledOften(self, id):
if CalledOftenManager.__instance is not None:
CalledOftenManager.__stop_run = True
while CalledOftenManager.__instance.isAlive():
pass # wait for the thread to terminate
CalledOftenManager.__stop_run = False
CalledOftenManager.__instance = DoIt(id, CalledOftenManager._stop_flag)
CalledOftenManager.__instance.start()
# Call Manager always
CalledOftenManager.calledOften(1)
CalledOftenManager.calledOften(2)
CalledOftenManager.calledOften(3)
Now, what I tried here is to make a controller for calling the thread DoIt. Its one approach to achieve what you need.
I created a small flask app to download images and text from pages, this can take verly long time, so
I would like to execute my requests in parell. I create threaded tasks. I would like this tasks to be able to download text or images from sites. I keep my tasks in a list of workers.
However I would like to select a method which thread will execute and then start whole thread.
How can I pass my method to thread run method()? Will this be a sub daemon thread?
import threading
import time
workers = []
class SavePage:
def get_text(self):
print("Getting text")
def get_images(self):
print("Getting images")
class Task(threading.Thread):
def __init__(self):
super().__init__()
self.save_page = SavePage()
def get_text_from_page(self):
self.save_page.get_text()
def get_images_from_page(self):
self.save_page.get_images()
if __name__ == '__main__':
task = Task()
task.get_images_from_page() # Why this executes, when I didn't put task.start() ?
# Moreover, is this really threaded? or just uses a method from class Task?
workers.append(task) # I want this list to be empty, after job is finished
print("".join(str(worker.is_alive()) for worker in workers)) #
print(workers)
task.get_images_from_page() # Why this executes, when I didn't put task.start() ?
# Moreover, is this really threaded? or just uses a method from class Task?
It's not threaded. It's just a normal method call in the main thread.
Thread.start is the method that will start Thread.run function inside another thread.
You could set some state in __init__ to choose which function to execute:
class Task(threading.Thread):
def __init__(self, action):
super().__init__()
self.save_page = SavePage()
self.action = action
def get_text_from_page(self):
self.save_page.get_text()
def get_images_from_page(self):
self.save_page.get_images()
def run(self):
if self.action == "text":
self.get_text_from_page()
elif self.action == "images":
self.get_images_from_page()
Keep in mind that threads can be run in simpler way by passing target function:
def target_func():
save_page = SavePage()
save_page.get_images()
t = threading.Thread(target=target_func)
t.start()
# or in this simple case:
save_page = SavePage()
t = threading.Thread(target=save_page.get_images)
t.start()
I need to be able to call a stop funtion of a running thread. I tried several ways to achieve this but so far no luck. I think I need a thread id but have no idea how this is done.
relevant code:
model:
import MODULE
class do_it():
def __init__(self):
self.on_pushButton_start_clicked()
return
def on_pushButton_start_clicked(self):
self.Contr = MODULE.Controller()
self.Contr.start()
def on_pushButton_stop_clicked(self):
if self.Contr:
self.Contr.stop()
self.Contr = None
return
module:
import thread
class Controller():
def __init__(self):
self.runme = False
def start(self):
"""Using this to start the controllers eventloop."""
thread.start_new_thread(self._run, ())
def stop(self):
"""Using this to stop the eventloop."""
self.runme = False
def _run(self):
"""The actual eventloop"""
self.runme = True
I think my issue lies here...
my controller:
"""I want to use this to control my model, that in turn controls the module"""
def start_module():
start=do_it().on_pushButton_start_clicked()
return 'Ran start function'
def stop_module():
stop=do_it().on_pushButton_stop_clicked()
return 'Ran stop function'
Regarding the thread module, this is what the docs say:
This module provides low-level primitives for working with multiple
threads […] The threading module provides an easier to use and
higher-level threading API built on top of this module.
Furthermore, there is no way to stop or kill a thread once it's started. This SO question goes further into detail and shows how to use a threading.Event to implement a stoppable thread.
The only difference is a daemon thread, which will be killed automatically when your main program exists.
I'm making a wxPython app that I need to update a value from the internet every 15 seconds. Is there any way I can have a function to set the value, and make it run in the background at this interval, without interrupting the program?
EDIT: Here's what I'm trying:
import thread
class UpdateThread(Thread):
def __init__(self):
self.stopped = False
UpdateThread.__init__(self)
def run(self):
while not self.stopped:
downloadValue()
time.sleep(15)
def downloadValue():
print x
UpdateThread.__init__()
What you want is to add a thread that runs your task at a specified pace.
You may have a look at this great answer here : https://stackoverflow.com/a/12435256/667433 to help you achieve this.
EDIT : Here is the code that should work for you :
import time
from threading import Thread # This is the right package name
class UpdateThread(Thread):
def __init__(self):
self.stopped = False
Thread.__init__(self) # Call the super construcor (Thread's one)
def run(self):
while not self.stopped:
self.downloadValue()
time.sleep(15)
def downloadValue(self):
print "Hello"
myThread = UpdateThread()
myThread.start()
for i in range(10):
print "MainThread"
time.sleep(2)
Hope it helps
I have made something similar to this:
-you need a thread to run in the background .
-And a define a 'custom' event , so that the tread can notify the UI when needed
Create the custom WX event
(MyEVENT_CHECKSERVER, EVT_MYEVENT_CHECKSERVER) =
wx.lib.newevent.NewEvent()
on UI "init" you can bind the event , and start the thread
# bind the custom event
self.Bind(EVT_MYEVENT_CHECKSERVER, self.foo)
# and start the worker thread
checkServerThread = threading.Thread(target=worker_checkServerStatus
,args=(self,) )
checkServerThread.daemon = True
checkServerThread.start()
the worker thread can be something like this ,ps. caller is the UI instance
def worker_checkServerStatus(caller):
while True:
# check the internet code here
evt = MyEVENT_CHECKSERVER(status='Some internet Status' ) #make a new event
wx.PostEvent(caller, evt) # send the event to the UI
time.sleep(15) #ZZZzz for a bit
Edit: miss read the question...
Another way to do that is with a timer:
import threading
stopNow = 0
def downloadValue():
print("Running downloadValue")
if not stopNow: threading.Timer(15,downloadValue).start()
downloadValue()
This is a classic pattern for repeating a function: the function itself adds a timed call to itself. To start the cycle, call the function (it returns immediately). To break the cycle set stopNow to 1.
Im trying to write a module for Python that prints out text for my program and displays a progress bar while i do something in the background. Im using the 'threading' module currently but open to suggestions if something else will make it easier.
what i want to know is two fold, how should i call this class elegantly and how should i stop these threads im creating?
this is what im currently doing:
tmp1 = textprint("hello this is text")
tmp1.start()
# do something
tmp1.stop()
these are the options ive considered and looked into so far:
using thread.name to find the name of the thread or having the thread
return a name to kill afterwards. OR passing a number for similar
thread identification afterwards. (a bit cumbersome and not my
favourite solution.)
sending a thread.event ? - from reading the docs i see an event can
be sent, perhaps that can be used to stop it?
or a with statement but im unclear how to use it in this context, plus i find most of the python docs extremely confusing and not written for me at all.
what i would like to do is something like this:
echo('hello') (prints progress bar etc)
- and then when i want to stop it echo.stop()
the obv. problem there though is that the stop function doesnt know which thread it is trying to stop.
Here is a skeleton of what im trying to do:
import time
import string
import threading
class print_text(threading.Thread):
def __init__(self,arg=None):
super(print_text,self).__init__()
self._stop = False
self.arg=arg
def run (self):
# start thread for text
print self.txt
while not self._stop:
print "rude words"
def echo (self,txt):
self.txt=txt
self.start()
def stop(self):
self._stop = True
def stopped(self):
return self._stop == True
def __enter__(self):
print "woo"
return thing
def __exit__(self, type, value, traceback):
return isinstance(value, TypeError)
if __name__ == '__main__':
print_text.start.echo('this is text') # dunt werk
with print_text.echo('this is text'):
time.sleep(3)
print "done"
and then call it like so:
echo('this is text')
i also guess to do this i would have to
import echo from print_text
the WITH way of doing things suggests putting an __enter__ and __exit__ bit in. i tried them and they didnt work and also, i didnt know what i was doing, really appreciate any help, thanks.
You were very close to having working code. There just needed to be a few minor fixups:
print_text is a class. It should be instantiated with print_text()
The start method returns an instance of print_text, you need to save that
in order to call stop and echo on it: t = print_text()
The enter method needs to return self instead of thing.
The exit method should either set _stop or call stop().
The echo method should return self so that it can be used with the with-statement.
Here is some working code that includes those minor edits:
import time
import string
import threading
class print_text(threading.Thread):
def __init__(self, arg=None):
super(print_text,self).__init__()
self._stop = False
self.arg=arg
def run (self):
# start thread for text
print self.txt
while not self._stop:
print "rude words"
def echo (self, txt):
self.txt=txt
self.start()
return self
def stop(self):
self._stop = True
def stopped(self):
return self._stop == True
def __enter__(self):
print "woo"
return self
def __exit__(self, type, value, traceback):
self._stop = True
return isinstance(value, TypeError)
if __name__ == '__main__':
t = print_text()
t.echo('this is text')
time.sleep(3)
t.stop()
with print_text().echo('this is text'):
time.sleep(3)
print "done"
The best way to stop a thread in Python is to politely ask it to stop. The best way to pass new data to a thread is with the Queue module.
Both are used in the code in this post, which demonstrates socket communication from a Python thread but is otherwise relevant to your question. If you read the code carefully you'll notice:
Using threading.Event() which is set by a method call from outside, and which the thread periodically checks to know if it was asked to die.
Using Queue.Queue() for both passing commands to the thread and receiving responses from it.
A thread name is useful if you could potentially have multiple subthreads running the same target at once and want to ensure that all of them are stopped. It seems like a useful generalization and doesn't seem too cumbersome to me, but beauty is in the eye of the beholder :-). The following:
starts a subthread to print a message and start a progressbar
stops the subthread using a name given when it was started.
It is much simpler code. Does it do what you want?
import time, threading
class print_text:
def __init__(self):
pass
def progress(self):
while not self._stop: # Update progress bar
print(".", sep="", end="")
time.sleep(.5)
def echo(self, arg="Default"): # Print message and start progress bar
print(arg)
self._stop = False
threading.Thread(target=self.progress, name="_prog_").start()
def stop(self):
self._stop = True
for t in threading.enumerate():
if t.name == "_prog_":
t.join()
tmp1 = print_text()
tmp1.echo("hello this is text")
time.sleep(10)
tmp1.stop()
print("Done")