Run thread and ask about data during work - python

I have a problem with my code. I'm running this code with thread, then I need to ask about variables SPEED, etc., but I don't know how. I'm still trying to do this, but I'm getting errors with thread.
BTW, I want to make a script that generates fake car data, and I need to fill a database, and then make some diagrams.
import time
import thread
class Test:
def __init__(self):
self.speed = 0
self.dist = 0
self.maxSpeed = 150
self.time = 6
self.fuel = 100
self.distance = 100
self.start = time.time()
self.elapsed = 0
def jazda(self):
while True:
self.speed += 1
if self.speed < self.maxSpeed:
time.sleep(1)
else:
time.sleep(60)
self.elapsed = time.time() - self.start
self.dist = (self.speed * self.elapsed) / 3600
print "Distance: ", self.dist
print "Speed: ", self.speed
print "Time: ", self.elapsed
if self.elapsed > self.time:
break
return 0
def SPEED(self):
return self.speed
and second script:
import test
import thread
import time
class Data:
def __init__(self):
self.test = test.Test()
def get_speed(self):
while True:
return self.test.SPEED()
time.sleep(2)
thread.start_new_thread( test.Test().jazda(), () )
thread.start_new_thread( obdData().get_speed, () )
The error I'm getting is:
thread.start_new_thread( Test().jazda(), () )
TypeError: first arg must be callable

I believe the problem is that the thread.start_new_thread method is expecting a method reference and not a method invocation i.e. test.Test().jazda is a method reference i.e. callable; however, test.Test().jazda() will return the result of the method (0 in this case) not a callable. Your start method should look like thread.start_new_thread(test.Test().jazda, ())

Related

Speeding up potentially long tasks

I decided to make a class for easily displaying animated gifs in Tkinter, which does work, but the process of gathering all the frames dynamically pretty much always takes a noticeable chunk of time and prevents anything else from happening until it has finished. I was wondering if there would be any way to speed it up or at a more efficient way of doing the same thing.
Here is the code for the class:
from tkinter import *
class animation:
def __init__(self,*args,**kwargs):
self.root=args[0]
self.label=Label(self.root)
self.label.grid()
self.image=kwargs["image"]
try:
self.delay=kwargs["delay"]
except KeyError:
self.delay=20
self.frames=[]
x=0
while True:
try:
img=PhotoImage(file=self.image,
format="gif -index {}".format(x))
self.frames.append(img)
x+=1
except:
break
def animate(self,y):
try:
self.label.configure(image=self.frames[y])
self.root.after(self.delay,lambda:self.animate(y+1))
except IndexError:
self.label.configure(image=self.frames[0])
self.root.after(self.delay,lambda:self.animate(1))
and here is how it would be used:
from tkinter import *
from modules.animation import animation
root=Tk()
cosmog=animation(root,image="cosmog.gif").animate(0)
cosmoem=animation(root,image="cosmoem.gif").animate(0)
lunala=animation(root,image="lunala.gif").animate(0)
root.mainloop()
Try like this with threading:
import threading
import time
def __init__(self, *args, **kwargs):
self.frames=[]
self.run_loop = True
self.x=0
self.taken = []
self.order = []
while self.run_loop:
threading.Thread(target=self.add_image).start()
def add_image(self):
try:
if self.x not in self.taken: # make sure not several threads add the same image index
self.taken.append(self.x)
self.x+=1
else:
return
# save local x before creating image, for the order
# all the other threads will increment self.x while Image is created
x = self.x
img=PhotoImage(file=self.image, format="gif -index {}".format(self.x))
self.frames.append(img)
self.order.append(x) # keep track of the order
if len(self.frames) == len(self.taken): # when finish
self.frames = [x for _,x in sorted(zip(self.order,self.frames))] # sort the frames to the order
except:
self.run_loop = False
I made a simple runable example without tkinter, using time.sleep(random amount of time), to simulate PhotoImage:
import threading
import time
from random import randint
class Test:
frames=[]
run_loop = True
x=0
taken = []
order = []
time = 0
def __init__(self):
while self.run_loop:
threading.Thread(target=self.add_image).start()
def add_image(self):
if self.x < 100:
if self.x not in self.taken: # make sure not several threads add the same image index
self.taken.append(self.x)
self.x+=1
else:
return
x = self.x
t = randint(1,10)/10.0
self.time += t
time.sleep(t) # PhotoImage random time.sleep 0 to 1 second
self.order.append(x)
self.frames.append(x)
if len(self.frames) == len(self.taken):
print("Frames before sort")
print(self.frames)
self.frames = [x for _,x in sorted(zip(self.order,self.frames))]
print("\nFrames after sort")
print(self.frames)
print("\nTime used combined: {} seconds".format(self.time))
else:
self.run_loop = False
t = Test()
This test shows a combined time used, to be around 50 seconds.
With a 100 threads, it does it in 1 second. The amount of time for the longest time.sleep, wich is 0 to 1 second.
So for you, it should not take more than the one longest PhotoImage call

How do I use the generate_events event?

The following python3 code is what I might have expected to generate a few calls to the doit event, followed by a call to the terminate event, which would stop the app, but only the first event fires. What am I doing wrong?
from circuits import Component, Event, Debugger
import time
times = []
class doit(Event):
"""doit Event"""
class terminate(Event):
"""terminate Event"""
class App(Component):
def __init__(self):
super().__init__()
self.interval = .1
self.last = 0
self.count = 0
def doit(self, origin):
times.append(("%s from A at %.03f" % (origin, time.time())))
self.count += 1
self.last = time.time()
def generate_events(self, event):
if self.last + self.interval < time.time():
event.stop()
self.fire(doit('ge'))
if self.count >= 5:
event.stop()
self.fire(terminate())
def terminate(self):
self.stop()
(Debugger() + App()).run()
print("\n".join(times))
I got the same behavior using event.reduce_time_left(0) instead of event.stop().
The main error in the example is that it doesn't reduce_time_left(time.time() - self.last + self.interval) when there is nothing to do.
generate_events fires once when the app starts. Each generator needs to set reduce_time_left() to the maximum reasonable time before firing again - so that it will certainly fire again by that time - whether something is generated or not. Reducing the time to 0 indicates that this cycle is complete (and events need to be fired).
The preferred solution uses Timer to implement the time functionality, reducing this example to the logic to display how it works.
from circuits import BaseComponent, Event, Timer, Debugger, handler
import time
class doit(Event):
"""doit Event"""
class App(BaseComponent):
timer = Timer(.1, doit('A'), persist=True)
def __init__(self):
super().__init__()
self.count = 0
#handler("doit")
def _doit(self, origin):
print("%s from A at %.03f" % (origin, time.time()))
self.count += 1
if self.count > 4:
self.stop()
(App() + Debugger()).run()

Mocking tool for python-3.3

I have a few classes that rely on time.perf_counter() to timestamp events and do things after a certain amount of time passes, like this:
class Alarm:
def setAlarm(self):
self.alarmed = False
self._saved = time.perf_counter()
def runStep(self):
now = time.perf_counter()
if now - self._saved > 1000.0 and self._saved != -1:
self.alarmed = True
self._saved = -1
I would like to test the class Alarm using a fake clock, it does not necessary to be a call to time.perf_counter() (though it would be more elegant if it does, I guess). I want that the fake clock does not increment by itself, but rather upon my command, like this:
alarm = Alarm()
alarm.setAlarm()
clock.increment(999.0)
alarm.runStep()
self.assertFalse(alarm.alarmed)
clock.increment(1.1) # tick another second
alarm.runStep()
self.assertTrue(alarm.alarmed)
Could you please advise on how to mock time.perf_counter() or mock my class for it, and what kind of tool should be used for this kind of job?
You can use unittest.mock.
For example:
import time
import unittest
import unittest.mock
class Alarm:
def setAlarm(self):
self.alarmed = False
self._saved = time.perf_counter()
def runStep(self):
now = time.perf_counter()
if now - self._saved > 1000.0 and self._saved != -1:
self.alarmed = True
self._saved = -1
class MockPerfCounter:
def __init__(self):
self.t = 0
def increment(self, n):
self.t += n
def perf_counter(self):
return self.t
class TestAlarm(unittest.TestCase):
def test_foo(self):
clock = MockPerfCounter()
with unittest.mock.patch('time.perf_counter', clock.perf_counter):
alarm = Alarm()
alarm.setAlarm()
clock.increment(999.0)
alarm.runStep()
self.assertFalse(alarm.alarmed)
clock.increment(1.1) # tick another second
alarm.runStep()
self.assertTrue(alarm.alarmed)
if __name__ == '__main__':
unittest.main()
Alterantively, instead of manual MockPerfCounter, you can also use unittest.mock.Mock:
class TestAlarm(unittest.TestCase):
def test_foo(self):
clock = unittest.mock.Mock()
clock.t = 0
with unittest.mock.patch('time.perf_counter', lambda: clock.t):
alarm = Alarm()
alarm.setAlarm()
clock.t += 999.0
alarm.runStep()
self.assertFalse(alarm.alarmed)
clock.t += 1.1
alarm.runStep()
self.assertTrue(alarm.alarmed)

How to get the total duration of media being played in PyQt4?

I am trying to write a small audio player in PyQt4. This is a part of the code I've written:
class Player(QMainWindow):
def __init__(self, fileLoc, parent = None):
super(QMainWindow, self).__init__()
self.totTime = 0
self.audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)
self.mediaObject = Phonon.MediaObject(self)
self.mediaObject.setTickInterval(1000)
self.mediaObject.tick.connect(self.tick)
self.mediaObject.stateChanged.connect(self.stateChanged)
Phonon.createPath(self.mediaObject, self.audioOutput)
#Define Play, Pause and Stop actions
self.playAction = QAction(self.style().standardIcon(QStyle.SP_MediaPlay),
"Play", self, enabled = False, triggered = self.mediaObject.play)
self.pauseAction = QAction(self.style().standardIcon(QStyle.SP_MediaPause),
"Pause", self, enabled = False, triggered = self.mediaObject.pause)
self.stopAction = QAction(self.style().standardIcon(QStyle.SP_MediaStop),
"Stop", self, enabled = False, triggered = self.mediaObject.stop)
#Initiate User Interface
self.userInterface()
self.timeDisp.display('00:00')
self.mediaObject.setCurrentSource(Phonon.MediaSource(fileLoc))
self.mediaObject.play()
def tick(self, time):
self.displayTime = QTime(0, (time / 60000) % 60, (time / 1000) % 60)
self.timeDisp.display(self.displayTime.toString('mm:ss'))
My problem is, I am unable to figure out how to get the total duration of the file being currently played. I have tried printing the output of mediObject.totalTime() at the end of init(). But it returned -1 for all the videos. mediObject.totalTime() inside tick() is returning incorrect duration (10 - 15 seconds longer than the actual duration).
Also, I may have to access the value of total duration from outside the class. How can I do this?
Thanks in advance.
You could connect the pause, play, and stop actions with other functions:
in the class __init__:
self.total_time = 0
self.playing = False
self.play_action = QAction(self.style().standardIcon((QStyle.SP_MediaPlay),"play",self)
self.play_action.triggered.connect(self.play_triggered_event)
and define the rest of the actions in a similar manner, connecting the triggered field of each QAction to a function
def play_triggered_event(self):
if not self.playing:
self.mediaObject.play
self.playing = True
self.start_time = time.clock()
def pause_triggered_event(self):
if self.playing:
self.mediaObject.pause
self.playing = False
self.total_time += (time.clock() - self.start_time)
def stop_triggered_event(self):
if self.playing:
self.mediaObject.stop
self.playing = False
print "Total time elapsed: " + str(self.total_time)
Basically, it's about saving some program state when the actions that affect the time elapsed are triggered.
To get the total time outside of the class, write an accessor for the class:
def get_total_time(self):
return self.total_time

Cancellable threading.Timer in Python

I am trying to write a method that counts down to a given time and unless a restart command is given, it will execute the task. But I don't think Python threading.Timer class allows for timer to be cancelable.
import threading
def countdown(action):
def printText():
print 'hello!'
t = threading.Timer(5.0, printText)
if (action == 'reset'):
t.cancel()
t.start()
I know the above code is wrong somehow. Would appreciate some kind guidance over here.
You would call the cancel method after you start the timer:
import time
import threading
def hello():
print "hello, world"
time.sleep(2)
t = threading.Timer(3.0, hello)
t.start()
var = 'something'
if var == 'something':
t.cancel()
You might consider using a while-loop on a Thread, instead of using a Timer.
Here is an example appropriated from Nikolaus Gradwohl's answer to another question:
import threading
import time
class TimerClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.event = threading.Event()
self.count = 10
def run(self):
while self.count > 0 and not self.event.is_set():
print self.count
self.count -= 1
self.event.wait(1)
def stop(self):
self.event.set()
tmr = TimerClass()
tmr.start()
time.sleep(3)
tmr.stop()
I'm not sure if I understand correctly. Do you want to write something like in this example?
>>> import threading
>>> t = None
>>>
>>> def sayHello():
... global t
... print "Hello!"
... t = threading.Timer(0.5, sayHello)
... t.start()
...
>>> sayHello()
Hello!
Hello!
Hello!
Hello!
Hello!
>>> t.cancel()
>>>
The threading.Timer class does have a cancel method, and although it won't cancel the thread, it will stop the timer from actually firing. What actually happens is that the cancel method sets a threading.Event, and the thread actually executing the threading.Timer will check that event after it's done waiting and before it actually executes the callback.
That said, timers are usually implemented without using a separate thread for each one. The best way to do it depends on what your program is actually doing (while waiting for this timer), but anything with an event loop, like GUI and network frameworks, all have ways to request a timer that is hooked into the eventloop.
Im not sure if best option but for me is woking like this:
t = timer_mgr(.....) append to list "timers.append(t)" and then after all created you can call:
for tm in timers:#threading.enumerate():
print "********", tm.cancel()
my timer_mgr() class is this:
class timer_mgr():
def __init__(self, st, t, hFunction, id, name):
self.is_list = (type(st) is list)
self.st = st
self.t = t
self.id = id
self.hFunction = hFunction
self.thread = threading.Timer(t, self.handle_function, [id])
self.thread.name = name
def handle_function(self, id):
if self.is_list:
print "run_at_time:", datetime.now()
self.hFunction(id)
dt = schedule_fixed_times(datetime.now(), self.st)
print "next:", dt
self.t = (dt-datetime.now()).total_seconds()
else:
self.t = self.st
print "run_every", self.t, datetime.now()
self.hFunction(id)
self.thread = threading.Timer(self.t, self.handle_function, [id])
self.thread.start()
def start(self):
self.thread.start()
def cancel(self):
self.thread.cancel()
Inspired by above post.
Cancelable and Resetting Timer in Python. It uses thread.
Features: Start, Stop, Restart, callback function.
Input: Timeout, sleep_chunk values, and callback_function.
Can use or inherit this class in any other program. Can also pass arguments to the callback function.
Timer should respond in middle also. Not just after completion of full sleep time. So instead of using one full sleep, using small chunks of sleep and kept checking event object in loop.
import threading
import time
class TimerThread(threading.Thread):
def __init__(self, timeout=3, sleep_chunk=0.25, callback=None, *args):
threading.Thread.__init__(self)
self.timeout = timeout
self.sleep_chunk = sleep_chunk
if callback == None:
self.callback = None
else:
self.callback = callback
self.callback_args = args
self.terminate_event = threading.Event()
self.start_event = threading.Event()
self.reset_event = threading.Event()
self.count = self.timeout/self.sleep_chunk
def run(self):
while not self.terminate_event.is_set():
while self.count > 0 and self.start_event.is_set():
# print self.count
# time.sleep(self.sleep_chunk)
# if self.reset_event.is_set():
if self.reset_event.wait(self.sleep_chunk): # wait for a small chunk of timeout
self.reset_event.clear()
self.count = self.timeout/self.sleep_chunk # reset
self.count -= 1
if self.count <= 0:
self.start_event.clear()
#print 'timeout. calling function...'
self.callback(*self.callback_args)
self.count = self.timeout/self.sleep_chunk #reset
def start_timer(self):
self.start_event.set()
def stop_timer(self):
self.start_event.clear()
self.count = self.timeout / self.sleep_chunk # reset
def restart_timer(self):
# reset only if timer is running. otherwise start timer afresh
if self.start_event.is_set():
self.reset_event.set()
else:
self.start_event.set()
def terminate(self):
self.terminate_event.set()
#=================================================================
def my_callback_function():
print 'timeout, do this...'
timeout = 6 # sec
sleep_chunk = .25 # sec
tmr = TimerThread(timeout, sleep_chunk, my_callback_function)
tmr.start()
quit = '0'
while True:
quit = raw_input("Proceed or quit: ")
if quit == 'q':
tmr.terminate()
tmr.join()
break
tmr.start_timer()
if raw_input("Stop ? : ") == 's':
tmr.stop_timer()
if raw_input("Restart ? : ") == 'r':
tmr.restart_timer()

Categories