Deleting a threaded timer class? - python

Imagine I have this code (not written the actual timer yet):
class Timer(threading.Thread):
def __init__(self, seconds):
self.runTime = seconds
threading.Thread.__init__(self)
def run(self):
time.sleep(self.runTime)
#do some other function
print 'Finished'
t = Timer(60)
t.start()
Once the run() method has finished running, is there some way to stop the thread, and delete the class instance?

The run() method is everything that runs in a thread, so when it has finished nothing is running anymore. Then t.is_alive() will return False. You can then delete the instance using del t, but that will just remove your reference to it. The actual deleting will be done by garbage collector some time later.

Related

awaiting future never reached, although set_result() is called

My example class uses only two methods,
async def run(): creates a asyncio.Future() and awaits it
def stop(): sets the result of the Future() created by the run() method
The idea is to use the python signal handler to call the stop() function once a signal is received. The stop() then sets the result of the Future() the run() is waiting for. So far so good, but this does not work. Actually, the run() method never notices that the Future() is done.
Example code:
import asyncio
import signal
class Foo:
def __init__(self):
self._stop = None
async def run(self):
print(f"1. starting foo")
self._stop = asyncio.Future()
await self._stop
print(f"4. 'stop' called, canceling running tasks...")
def stop(self):
print(f"3. stopping foo")
self._stop.set_result(None)
f = Foo()
loop = asyncio.new_event_loop()
def signal_handler(_, __):
print(f"2. signal handler: call Foo.stop()")
f.stop()
signal.signal(signal.SIGINT, signal_handler)
loop.run_until_complete(f.run())
print(f"5. bye")
and the output is:
1. starting foo
2. signal handler: call Foo.stop()
3. stopping foo
That's it. The fourth print entry is never called. Although the self._stop Future is done after setting the result.
Does anyone have any idea what I am doing wrong and what I am missing?
Any help would be greatly appreciated!
I cannot reproduce your problem, but it is quite possible that it'll happen on different operating systems.
Per loop.add_signal_handler:
Unlike signal handlers registered using signal.signal(), a callback registered with this function is allowed to interact with the event loop.
The usual culprit that causes those issues is the event loop not waking up from outside input.
There are 2 solutions for your issue:
If you're using unix, change signal.signal() to loop.add_signal_handler().
If not, try changing f.stop() to loop.call_soon_threadsafe(f.stop). It will make sure that the event loop wakes up correctly.
Irrespective to that, you have a couple of different issues arising from using asyncio.new_event_loop() and not assigning the loop to the thread or cleaning up correctly. I suggest you to use asyncio.run().

Python threading: wait for thread to stop then execute function

I'm trying to run a function after my thread has completed but the function is not called. Code structure:
class():
def functiontocall() # uses data calculated in thread for plotting. only works when thread is complete
do something with self.A
def watchthread():
thread()
functiontocall()
# since this function depends on variable A, it throws an error.
# I tried: if thread.join == True: functiontocall but this did not call the function.
def thread():
def run():
pythoncom.CoInitialize()
--- do stuff --
for i in 1000:
thousands of calculations while updating state in GUI ---
A = result
self.A = A
thread = threading.Thread(target=run)
thread.start()
note: i removed 'self' for simplicity.
thread.join should tell me when the thread has finished but for some reason i still cant run the functiontocall.
Is this a bad way of organizing threads in general?
Edit: I can call the function after the thread is finished but I cannot access variables when the thread is running. e.g. 0-100% progress for a progress bar in my GUI. when I use:
def watchthread():
thread()
thread.join()
functiontocall()
I cannot update the status of the thread in my GUI. It just waits until the calculations are finished then runs functiontocall().
Because you're using threads, once the thread had started Python will move onto the next thing, it will not wait for the thread to finish unless you've asked it to.
With your code, if you want to wait for the thread function to finish before moving on then it doesn't sound like you need threading, a normal function would run, complete, and then Python will move onto running functiontocall()
If there's a reason you need to use threads which isn't coming across in the example then I would suggest using a thread.join()
threads = [] # list to hold threads if you have more than one
t = threading.Thread(target=run)
threads.append(t)
for thread in threads: # wait for all threads to finish
thread.join()
functiontocall() # will only run after all threads are done
Again, I'd suggest relooking at whether threads is what you need to use here as it doesn't seem apparent.
To update this answer based on the new information, this may be the way you want to have a variable be accessible. In this case the threads would all update your class variable A, your GUI update function also reads this periodically and updates your GUI.
class ThisClass():
def __init__(self):
self.A = 0
def function_to_call(self):
while self.A != 100: # assuming this is a progress bar to 100%
# update in GUI
def run(self):
# does calculations
with lock: # to prevent issues with threads accessing variable at the same time
self.A += calculations
def progress(self):
threads = [] # list to hold threads if you have more than one
t = threading.Thread(target=run)
threads.append(t)
f = threading.Thread(target=self.function_to_call)
threads.append(f)
for thread in threads:
thread.start()
for thread in threads: # wait for all threads to finish
thread.join()

PySide - QThread running but not entering slot connected to signal 'started'

I thought I've read it all about threading in Qt, but apparently I'm getting it wrong. I'm stuck with this stuff for some time now, so I would really appreciate your help a lot.
So, I created a class that starts a thread in its __init__ method:
class MyClass(object):
def __init__(self):
(...)
self.thread = QtCore.QThread(parent)
worker = Worker()
QtCore.QObject.connect(self.thread, QtCore.SIGNAL('started()'), worker,
QtCore.SLOT('doWork()'))
QtCore.QObject.connect(worker, QtCore.SIGNAL('finished()'), self.thread,
QtCore.SLOT('quit()'))
QtCore.QObject.connect(worker, QtCore.SIGNAL('finished()'), worker,
QtCore.SLOT('deleteLater()'))
QtCore.QObject.connect(self.thread, QtCore.SIGNAL('finished()'),
self.thread, QtCore.SLOT('deleteLater()'))
worker.moveToThread(self.thread)
self.thread.start()
Worker class looks like that:
class Worker(QtCore.QObject):
(some signals)
def doWork(self):
print "doing my work"
The problem is that my doWork slot is never executed, although the thread is running.
After creating instance of MyClass, let's say:
obj = MyClass()
I can call:
obj.thread.isRunning()
which returns True.
I assume that signal 'started' is not emitted, because of instantly exiting the method where thread was created (when I add sleep after starting thread, it enters doWork slot). I wonder how such situation should be handled properly.
Please let me know if I did not explain my problem clearly.
Thank you all for help in advance.
Your worker is being garbage collected after the MyClass constructor returns. Make worker a member of MyClass so that it persists beyond the constructor.
self.worker = Worker()

Concurrent execution of QThread or QRunnable objects in Python

I have the following code:
from PySide.QtCore import *
import time
class GUI(object):
IDLIST = [i for i in xrange(20)]
UNUSEDIDS = [i for i in xrange(20)]
def __init__(self):
print "GUI CLASS INITIALIZED!"
worker = Worker()
worker2 = Worker2()
threadpool = QThreadPool()
threadpool.setMaxThreadCount(10)
for i in xrange(5):
#Alternate between the two
#threadpool.start(worker)
#worker2.start()
#classmethod
def delegator(self):
"""Irrelevant to the question, I need this method for something else"""
USEDIDS = []
toUse = self.UNUSEDIDS[0]
USEDIDS.append(toUse)
self.UNUSEDIDS.pop(0)
return toUse
class Worker(QRunnable):
def __init__(self, parent=None):
super(Worker, self).__init__(parent)
def run(self):
#idInUse = getattr(GUI, "delegator")
idInUse = GUI.delegator()
print "Hello world from QRunnable", idInUse
#time.sleep(5)
class Worker2(QThread):
def __init__(self, parent=None):
super(Worker2, self).__init__(parent)
def run(self):
idInUse = GUI.delegator()
print "Hello world from QThread", idInUse
s = time.time()
GUI()
print "Done in %s" % ((time.time()-s) * 1000)
I think the desired effect is obvious from the code. I want the "Hello world from QThread/QRunnable " to be shown. Since I am writing a multi-threaded application, in my GUI __init__ part I have the loop that starts concurrent threads.
The thing is that, with QRunnable it works just fine. All the 5 threads I specified get executed at once, concurrently. With QThread, however, that is not the case. Instead, I get the following error:
QThread: Destroyed while thread is still running
And it is not executed at all.
Normally I would not at all mind using the QRunnable, however, it does not derive from QObject (so I can't directly emit signals though I can construct a QObject() within it) and also it does not have the .stop() method which I badly need. Googling revealed that there is no way to stop a QRunnable from executing? On the other hand, QThread has both of these methods that I need.
So I guess my question is either how to make multiple same QThreads run concurrently, or how to terminate an execution of a QRunnable?
(also please bear in mind that the python's built-in threading module is out of the question)
The QThread: Destroyed while thread is still running-exception happens because you never wait for your threads to finish, and you don't keep any reference to them (neither to worker, worker2 or threadpool, so when your __init__ finishes it gets destroyed.
if you keep a reference to this objects, then is should work:
def __init__(self):
print "GUI CLASS INITIALIZED!"
self.worker = Worker()
self.worker2 = Worker2()
self.threadpool = QThreadPool()
self.threadpool.setMaxThreadCount(10)
for i in xrange(5):
#Alternate between the two
self.threadpool.start(worker)
# this is wrong, by the way!
# you should create 5 workers, not call start 5 times...
self.worker2.start()
and calling the wait/waitForDone methods on the thread/pool is even better.
For a QThreadPool this implicily happens when it's (C++) destructor is called. If that wasn't the case, then your program wouldn't have worked with QRunnables in the first place eiter. For the QThread nothing like this happens and it's even mentioned that it will probably result in a crash. So it's better to explicitly wait for the threads to finish...
also, i hope you already know this

Python thread doesn't work as expected

well,I wrote a little snappet trying to know how to use python threading .
But strangely the following code just quit quickly without the expected output.
Is it because I shouldn't spawn threads by overiding the run() method?
import threading
from time import sleep
class mythread(threading.Thread):
def __init__(self,target=None,thread_num=5):
threading.Thread.__init__(self,target=None)
self.thn = thread_num
def run(self):
for i in range(self.thn):
t = threading.Thread(target=self.myfunc)
t.start()
t.join()
myfunc(self.thn)
def myfunc(num):
print num,'\tI am doing sth.'
sleep(0.5)
print num,'\tI have done it.'
mythread()
You need to start the thread to make it actually do something:
t = mythread()
t.start()
If you bother to accept a target parameter in your constructor (why?), you shouldn't ignore this parameter. Maybe you want to pass it on to the Thread constructor. (Why?)
When you write mythread(), you instantiate the object. THe default constructor will be called, so __init__() will be executed.
You constructor doesn't have the any instruction of starting the thread.

Categories

Resources