Calling a def from a thread - python-3.x

Does any one know how to call a def form a thread.
Clock Program:
import sys
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
from time import sleep
import threading
class MyThread ( threading.Thread ):
def mclock(): # function that it can't call
x = 1
z = 0
while x != -1:
Label(mGui,text = str(x) + "second(s)").pack()
x = x+1
sleep(1)
if x == 60:
x = 1
z = z+1
Label(mGui, text= str(z) + " minute(s) has past.").pack()
return
return
MyThread().start()
mGui = Tk()
mGui.geometry("300x200+100+100")
mGui.title("Jono's Clock")
menubar = Menu(mGui)
filemenu = Menu(menubar, tearoff = 0)
filemenu.add_command(label = "Clock",command = mclock) # can't use function
menubar.add_cascade(label = "File",menu = filemenu)
mGui.config(menu = menubar)
mGui.mainloop()
If any one sees any other errors please state. I am also using windows 7 and python 3.3.

There are several syntax errors in the code you've posted, and I'm not sure exactly what you intended with them, so here's an overview of how to run stuff from threads.
If you want your thread to run your own code from a custom thread class, the usual way to do that is to put the code in a method named run, which will be executed automatically when the thread is started:
import threading
class MyThread(threading.Thread):
def run(self):
# do your stuff here
print("Hello World")
MyThread().start()
Alternatively, if you don't need a class, you can create your function at the top level of your module, and pass it as an argument to threading.Thread's constructor:
def my_function():
print("Hello World")
threading.Thread(target=my_function).start()
Note that you often want to keep a reference to the thread object, rather than letting it go as the code above does. This requires you to use two lines to create and then start the thread:
thread = MyThread() # or the alternative version
thread.start()
This lets you later do:
thread.join()
Which ensures that the thread has finished its work.

Related

Why serial code is faster than concurrent.futures in this case?

I am using the following code to process some pictures for my ML project and I would like to parallelize it.
import multiprocessing as mp
import concurrent.futures
def track_ids(seq):
'''The func is so big I can not put it here'''
ood = {}
for i in seq:
# I load around 500 images and process them
ood[i] = some Value
return ood
seqs = []
for seq in range(1, 10):# len(seqs)+1):
seq = txt+str(seq)
seqs.append(seq)
# serial call of the function
track_ids(seq)
#parallel call of the function
with concurrent.futures.ProcessPoolExecutor(max_workers=mp.cpu_count()) as ex:
ood_id = ex.map(track_ids, seqs)
if I run the code serially it takes 3.0 minutes but for parallel with concurrent, it takes 3.5 minutes.
can someone please explain why is that? and present a way to solve the problem.
btw, I have 12 cores.
Thanks
Here's a brief example of how one might go about profiling multiprocessing code vs serial execution:
from multiprocessing import Pool
from cProfile import Profile
from pstats import Stats
import concurrent.futures
def track_ids(seq):
'''The func is so big I can not put it here'''
ood = {}
for i in seq:
# I load around 500 images and process them
ood[i] = some Value
return ood
def profile_seq():
p = Profile() #one and only profiler instance
p.enable()
seqs = []
for seq in range(1, 10):# len(seqs)+1):
seq = txt+str(seq)
seqs.append(seq)
# serial call of the function
track_ids(seq)
p.disable()
return Stats(p), seqs
def track_ids_pr(seq):
p = Profile() #profile the child tasks
p.enable()
retval = track_ids(seq)
p.disable()
return (Stats(p, stream="dummy"), retval)
def profile_parallel():
p = Profile() #profile stuff in the main process
p.enable()
with concurrent.futures.ProcessPoolExecutor(max_workers=mp.cpu_count()) as ex:
retvals = ex.map(track_ids_pr, seqs)
p.disable()
s = Stats(p)
out = []
for ret in retvals:
s.add(ret[0])
out.append(ret[1])
return s, out
if __name__ == "__main__":
stat, retval = profile_parallel()
stat.print_stats()
EDIT: Unfortunately I found out that pstat.Stats objects cannot be used normally with multiprocessing.Queue because it is not pickleable (which is needed for the operation of concurrent.futures). Evidently it normally will store a reference to a file for the purpose of writing statistics to that file, and if none is given, it will by default grab a reference to sys.stdout. We don't actually need that reference however until we actually want to print out the statistics, so we can just give it a temporary value to prevent the pickle error, and then restore an appropriate value later. The following example should be copy-paste-able and run just fine rather than the pseudocode-ish example above.
from multiprocessing import Queue, Process
from cProfile import Profile
from pstats import Stats
import sys
def isprime(x):
for d in range(2, int(x**.5)):
if x % d == 0:
return False
return True
def foo(retq):
p = Profile()
p.enable()
primes = []
max_n = 2**20
for n in range(3, max_n):
if isprime(n):
primes.append(n)
p.disable()
retq.put(Stats(p, stream="dummy")) #Dirty hack: set `stream` to something picklable then override later
if __name__ == "__main__":
q = Queue()
p1 = Process(target=foo, args=(q,))
p1.start()
p2 = Process(target=foo, args=(q,))
p2.start()
s1 = q.get()
s1.stream = sys.stdout #restore original file
s2 = q.get()
# s2.stream #if we are just adding this `Stats` object to another the `stream` just gets thrown away anyway.
s1.add(s2) #add up the stats from both child processes.
s1.print_stats() #s1.stream gets used here, but not before. If you provide a file to write to instead of sys.stdout, it will write to that file)
p1.join()
p2.join()

Having trouble running two loops at the same time python

I want to run two loops at the same time in python (first_mainloop(), second_mainloop()), I use threading but it doesn't work at this situation (only first loop runs and after it gets closed second loops starts running) any ideas?
import threading
import runpy
from tkinter import *
root = Tk()
import os
def first_mainloop():
p1 = PhotoImage(file='Screenshot_13-removebg-preview.png')
root.iconphoto(False, p1)
frameCnt = 12
frames = [PhotoImage(file='light_ai_design_by_gleb.gif',format = 'gif -index %i' %(i)) for i in range(frameCnt)]
# set window size
root.geometry("500x400")
root.title("Assistant")
def update(ind):
frame = frames[ind]
ind += 1
if ind == frameCnt:
ind = 0
label.configure(image=frame)
root.after(100, update, ind)
label = Label(root)
label.pack()
root.resizable(False, False)
root.after(0, update, 0)
root.mainloop()
def second_mainloop():
runpy.run_path("main.py")
thread1 = threading.Thread(target=first_mainloop())
thread1.start()
thread2 = threading.Thread(target=second_mainloop())
thread2.start() ```
I think the problem is in parentheses, because when you write this thread1 = threading.Thread(target=first_mainloop()), you call the function. So remove the brackets, it should be something like: thread1 = threading.Thread(target=first_mainloop)
Here is great explanation of your problem: https://thispointer.com/python-how-to-create-a-thread-to-run-a-function-in-parallel/

How to thread with tkinter in python3 using queue?

I'm trying to thread definitions in tkinter using queue in specifically python3
I've had similar code in python2 work great using a similar method without queue but in python3 from what i've read tkinter doesn't allow for multithreading with gui. I found some examples that uses Queue process. They outline i'm suppose to create an Queue object, a new thread with access to that queue and check for input in the main thread
#!/usr/bin/python3
from tkinter import *
import time
import threading
import queue
import subprocess
def temp_sensor(queue_list):
warning = 0
while True:
var = "cat /sys/class/thermal/thermal_zone*/temp"
temp_control = subprocess.check_output([var], shell=True)
temp_length = len(temp_control)
temp_control = temp_control[35:]
temp_control = temp_control[:-4]
temp_control = int(temp_control)
degree_sign= u'\N{DEGREE SIGN}'
displayed_temp = "Tempature: " + str(temp_control) + degree_sign + "C"
if temp_control > 79:
warning = warning + 1
if warning == 3:
print ("Warning Core Tempature HOT!")
warning = 0
if temp_control > 90:
time.sleep(3)
print ("Warning EXTREMLY to HOT!!!")
queue_list.put(displayed_temp)
time.sleep(1)
class Gui(object):
def __init__(self, queue_list):
self.queue_list = queue_list
self.root = Tk()
self.root.geometry("485x100+750+475")
main_tempature_status = StringVar(self.root)
Ts = Entry(self.root, textvariable=main_tempature_status)
Ts.pack()
Ts.place(x=331, y=70, width=160, height=25)
Ts.config(state=DISABLED, disabledforeground="Black")
self.root.after(1000, self.read_queue)
def read_queue(self):
try:
temp = self.queue.get_nowait()
self.main_tempature_status.set(temp)
except queue_list.Empty:
pass
self.root.after(1000, self.read_queue)
if __name__ == "__main__":
queue_list = queue.Queue()
gui = Gui(queue_list)
t1 = threading.Thread(target=temp_sensor, args=(queue_list,))
t1.start()
gui.root.mainloop()
My desired result is to run a some of these definitions to do various tasks and display their variables in the tkinter entry using python3.
when i run my code it gives me the variable from the queue but it won't post to the GUI. please forgive my less then pythonic code.
Change you Gui class to this:
class Gui(object):
def __init__(self, queue_list):
self.queue_list = queue_list
self.root = Tk()
self.root.geometry("485x100+750+475")
self.main_tempature_status = StringVar(self.root)
self.Ts = Entry(self.root, textvariable=self.main_tempature_status)
self.Ts.pack()
self.Ts.place(x=331, y=70, width=160, height=25)
self.Ts.config(state=DISABLED, disabledforeground="Black")
self.root.after(1000, self.read_queue)
def read_queue(self):
try:
temp = self.queue_list.get_nowait()
self.Ts.config(state=NORMAL)
self.main_tempature_status.set(temp)
self.Ts.config(state=DISABLED)
except queue.Empty:
pass
self.root.after(1000, self.read_queue)
Explanation:
variable main_temperature_status is used in function read_queue as class variable, but not defined as class variable.
You cannot show the change in value of Entry widget if it is always disabled, so enabling it before value change in read_queue.

Updating PyQt4 GUI while in loop

I would like to show progress of calculation if in my GUI. To do so I would like to update my PyQt4 label each time a calculation is made. I know that I am supposed to use thread to do it, but it doesn't work. Nothing changes, and after while loop is complete, the label is updated to "100%".Even though the thread is working the value still won't update smoothly. There are comments in my code explaining what is what. Please help me :)
from PyQt4 import QtGui, QtCore
import time
class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal(int)
def __init__(self, progress, parent=None):
super(MyThread, self).__init__(parent)
self.progress = progress #progress is a PyQt4 label object
def update_progress(self, value):
self.progress.setText(QtGui.QApplication.translate("Dialog", "Progress: %s " % value, None))
print "I was called", value
print self.progress #prints <PyQt4.QtGui.QLabel object at 0x0000000008151708>
#as you can see the object is passed all right
def run(self, value):
self.trigger.emit(value)
class Calculus:
def __init__(self):
print "object created"
#staticmethod
def euler(b,h,progress):
#progress is a PyQt4 label object, b and h are some integers
actions_done = 0
actions_number = b / h
thread = MyThread(progress)#create a thread
thread.trigger.connect(thread.update_progress)#connect it with a update function
thread.start()#start the thread
while t <= b:
actions_done+=1
progress_value = (actions_done/actions_number)*100
thread.run(progress_value)#emit signal?
t += h
thread.terminate()
#EDIT, here is my solution but with memory leaking problem
from PyQt4 import QtGui
class Calculus:
def __init__(self):
print "object created"
#staticmethod
def update_progress(self,value,ui_object):
ui_object.setText(QtGui.QApplication.translate("Dialog", "Progress: %s %%" % value, None))
#MEMORY LEAK WHEN UPDATING TOO MUCH (H=0.0001 AND B=1000)
QtGui.QApplication.processEvents() #update gui for pyqt
#staticmethod
def euler(b,h,progress):
actions_done = 0
actions_number = b * (1./h) #t = t+h. When h = 0.01 we need to perform t=t+h 100(1/h) times to get 1.
#when t varies from 0 to b, then we need to multiply this 1 * b(end time)
#so we get b * (1/h) as a number of actions to perform
scale = actions_number * 0.01
while t <= b:
actions_done+=1
progress_value = (actions_done/actions_number)*100
if (actions_done % scale == 0):
Calculus.update_progress(None,progress_value, progress)
t += h
Calling thread.run() in the way that you are does not do what you think it does. Currently it is simply executing the thread.run() method in the main thread.
It is the call to thread.start() which starts the thread, and automatically calls the thread.run() method. As such, you need the while loop inside the thread.run() method.
This is because you want to pass complete control over to the thread, and finish the euler method so that control can be returned to the GUI event loop (so it can process redraws, and the method to update the progress bar) as soon as possible. You should not be trying to manage the threads execution from the main thread.

Why aren't breakpoints working on the Swing Event Dispatch Thread in PyDev?

I'm using Jython, Swing, and PyDev (Eclipse).
Breakpoints are not being hit on any code that runs on the EDT (aka AWT Event Queue?).
This includes:
Functions that are invoked from a Swing event (eg JButton click)
Functions that, via a decorator, are run through SwingUtilities.invokeLater() (See the last example here.
Functions that registered as hooks to a Java package (socket class), that I'm using.
Swing event code to reproduce:
from javax.swing import JFrame, JButton
def TestFunc(event):
#breakpoints in this function don't work
print "Hey"
if __name__ == '__main__':
mainWindow = JFrame('Test',
defaultCloseOperation = JFrame.EXIT_ON_CLOSE,
size = (1024, 600))
mainWindow.add(JButton("Hey", actionPerformed = TestFunc))
mainWindow.visible = True
invokeLater() code to reproduce:
from java.lang import Runnable
from javax.swing import SwingUtilities
import threading
class foo(Runnable):
def __init__(self, bar):
self.bar = bar
def run(self):
#breakpoints in this function don't work
print threading.currentThread()
print self.bar
if __name__ == '__main__':
myFoo = foo(5)
SwingUtilities.invokeLater(myFoo)
It's actually a Jython issue.
I.e.: in the code below, when TestFunc is called, the print from the trace_dispatch should be called, but it's not.
So, the Jython tracing implementation is not calling the tracing function as it should in that situation. You can 'help' the PyDev debugger by calling import pydevd;pydevd.settrace(suspend=False) so that the debugger discovers about that frame (i.e.: in the start of TestFunc add that line of code).
Note that if you don't pass the suspend=False, it'll act as a breakpoint in the code and will stop the execution at that line.
import sys
import threading
def trace_dispatch(frame, event, arg):
print frame.f_code.co_filename, frame.f_code.co_name
sys.settrace(trace_dispatch)
threading.settrace(trace_dispatch)
from javax.swing import JFrame, JButton
def TestFunc(event):
print "Hey"
if __name__ == '__main__':
mainWindow = JFrame('Test',
defaultCloseOperation = JFrame.EXIT_ON_CLOSE,
size = (1024, 600))
mainWindow.add(JButton("Hey", actionPerformed = TestFunc))
mainWindow.visible = True

Resources