kivy- need to wait until the thread is finish - multithreading

i have in my app thread that append something to list and then i want to print it in other screen, but, the program run the thread after the print and it is give me error that there is no thing in my list. i am need to stop the program until the thread done, how can i do this? i tried to use .join() but it is didnt work... thanks for help
my app:
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
self.cols = 2
self.add_widget(Label(text='username'))
self.username = TextInput(multiline=False)
self.add_widget(self.username)
self.add_widget(Label(text='Password'))
self.password = TextInput(multiline=False, password=True)
self.add_widget(self.password)
self.submit_button = Button(text='sumbit',size_hint=(.5,
.25),font_size=20)
self.submit_button.bind(on_press=self.submit_username)
self.add_widget(self.submit_button)
def submit_username(self, *args):
self.msg=threading.Thread(target=send_data(self.username.text))
self.msg.start()
self.msg.join()
sm.current = 'searchi'
sm.transition.direction = 'left'
def send_data(name):
my_socket = socket.socket()
my_socket.connect(('127.0.0.1', 8093))
my_socket.send(name.encode('utf-8'))
name,address = my_socket.recvfrom(1024)
msg = name.decode('utf-8')
alist.append(msg)
my_socket.close()
# Declare both screens
class Searchi(Screen):
def __init__(self, **kwargs):
super(Searchi, self).__init__(**kwargs)
self.add_widget(Label(text=alist[0]))
the list have to "msg" if i am delete the line"self.add_widget(Label(text=alist[0]))" then it is no problem in the recv line. i just need to wait until the thread is finish.

Why bother with a Thread if you are going to wait for it anyway? You could just call send_data(self.username.text) and be done with it.
But doing this is usually bad practice (doing blocking calls without a thread, or waiting for the thread to finish in a blocking way, which is equivalent), what you want, instead of waiting for the task to be done before proceeding, is to react to the task being done, that is, at the end of your thread, do something that will allow your app to proceed.
you could have a callback to move your user to the new screen, called at the end of the thread.
def submit_username(self, *args):
def callback():
sm.current = 'searchi'
sm.transition.direction = 'left'
threading.Thread(target=send_data(self.username.text, callback).start()
def send_data(name, callback):
my_socket = socket.socket()
my_socket.connect(('127.0.0.1', 8093))
my_socket.send(name.encode('utf-8'))
name,address = my_socket.recvfrom(1024)
msg = name.decode('utf-8')
alist.append(msg)
my_socket.close()
callback()
if you want your user to touch anything while the action happens, i would advise putting a Popup with auto_dismiss=False, and a content indicating that data is being processed, and to close it in the callback.

Related

wxpython postevent from coroutine to a parent window (modal)

I got a coroutine running to catch events sent by a footswitch device. This coroutine is launched from the main window as following.
class FootswitchMonitor(wx.Frame):
def __init__(self, parent, title):
super().__init__(parent, title=title,
size=(350, 150))
self.InitUI()
StartCoroutine(self.footswitch_callback, self)
self.Bind(EVT_FOOTSWITCH, self.pedal)
def on_footswitch(self, evt):
print(f"eid: {evt.GetId()} code: {evt.code} ")
async def footswitch_callback(self):
device = get_footswitch_device()
device.grab()
key_pressed = None
async for ev in device.async_read_loop():
if ev.type == 1 and ev.value == 1: # only key events and key_down
if key_pressed != ev.code:
event = footswitch_event(code=ev.code)
wx.PostEvent(self, event)
key_pressed = ev.code
else:
key_pressed = None
def setup_footswitch(self, event):
cDialog = ConfigDialog(None)
cDialog.ShowModal()
cDialog.Destroy()
In order to setup the device I use a ConfigDialog dialog box where I'd like to bind the same EVT_FOOTSWITCH.
class ConfigDialog(wx.Dialog):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.InitUI()
self.SetSize(350, 450)
self.SetTitle("Configuration")
self.Bind(EVT_FOOTSWITCH, self.footswitch_setup_callback)
And this is where it hurts. The main coroutine has FootswitchMonitor frame as target: wx.PostEvent(self, event). So the ConfigDialog windows won't get it.
I cannot run another coroutine with this device in the parent windows because it is grabed, which is locked by the main coroutine.
So my question is how can I catch the EVT_FOOTSWITCH in ConfigDialog a parent windows. Is it possible to post the event globaly? Is it possible to stop the main coroutine to run anotheone in the modal window?
I have something similar where I run reading the footpedal in a separate thread.
If the user wishes to reconfigure the pedal settings, I simply stop the thread, for the duration of the reconfiguration, then restart it.
Stopping the thread also ungrabs the device.
I do insist the program is restarted, as I only read the configuration of the footpedal's settings at program start. I found it less complicated this way.
Your other option, if you wish to attack it from a different angle, is to Unbind the event i.e. self.Unbind(EVT_FOOTSWITCH) and ungrab the device.
Then Bind it to your reconfiguration routine, which Unbind's when it finishes and finally rebind the event back to the original, whilst regrabbing the device, when you return to the main app.
My rather vast code can be perused at https://sourceforge.net/projects/footswitch2 , if you need further clues.
When browsing the file fs2.py search for PedalThread

Invoke tkinter trace callback AFTER a certain variable delay has been achieved

I have a tkinter application that searches through a list of about 100000 wordlist when user types into the Entry widget (using trace with write callback to capture change in Entry variable).
I want to implement sort of a delay in order to NOT invoke the trace callback (to search the entire 100k wordlist) at EVERY keystroke (as the user might still be typing and it can become rather jerky/slow to invoke the callback function for each keystroke), rather I want to employ some sort of a min time to wait for additional input/keystroke AND/OR a max time since the first key was pressed BEFORE invoking the trace callback function.
I tried implementing a sleep but that is just a blocking call and does not achieve the desired affect. Here is some sample code where entering the string 'password' will invoke the callback (since this is literally just checking against the string 'password', it is super fast, yet in my app I loop over 100k word list for each keystroke which becomes slow). Thank You!
import tkinter as tk
from tkinter import ttk
class App(tk.Tk):
SUCCESS = 'Success.TLabel'
def __init__(self):
super().__init__()
self.title('Enter <password>')
self.geometry("200x120")
self.passwordVariable = tk.StringVar()
self.passwordVariable.trace('w', self.validate)
password_entry = ttk.Entry(
self, textvariable=self.passwordVariable) #, show='*'
password_entry.grid(column=0, row=1)
password_entry.focus()
self.message_label = ttk.Label(self)
self.message_label.grid(column=0, row=0)
def set_message(self, message, type=None):
self.message_label['text'] = message
if type:
self.message_label['style'] = type
def validate(self, *args):
confirm_password = self.passwordVariable.get()
if confirm_password == "password":
self.set_message(
"Success: The new password looks good!", self.SUCCESS)
return
if confirm_password.startswith("pas"):
self.set_message('Warning: Keep entering the password')
if __name__ == "__main__":
app = App()
app.mainloop()
I tried to understand what your current code does so I can implement the function here, but I've had no luck. Hopefully you being the author can implement this example onto your code.
The idea here is to schedule a callback to run after x seconds and if it is already scheduled, then cancel it. Sort of like a timer, if you think about it.
from tkinter import *
root = Tk()
SECONDS_TO_WAIT = 1
rep = None
def typing(*args):
global rep
if rep is None:
writing.config(text='Typing...')
else:
root.after_cancel(rep) # if already scheduled, then cancel it
rep = root.after(SECONDS_TO_WAIT*1000, caller)
def caller(*args):
global rep
writing.config(text='Not typing')
rep = None # Set it to None if `caller` GETS executed
var = StringVar()
entry = Entry(root,textvariable=var)
entry.pack(padx=10,pady=10)
entry.focus_force()
writing = Label(root,text='Not typing')
writing.pack()
var.trace('w',typing)
root.mainloop()
This will execute typing each time the entry widget is edited/written to. And according to the conditions inside the function, caller gets executed.

Dart: Store heavy object in an isolate and access its method from main isolate without reinstatiating it

is it possible in Dart to instantiate a class in an isolate, and then send message to this isolate to receive a return value from its methods (instead of spawning a new isolate and re instantiate the same class every time)? I have a class with a long initialization, and heavy methods. I want to initialize it once and then access its methods without compromising the performance of the main isolate.
Edit: I mistakenly answered this question thinking python rather than dart. snakes on the brain / snakes on a plane
I am not familiar with dart programming, but it would seem the concurrency model has a lot of similarities (isolated memory, message passing, etc..). I was able to find an example of 2 way message passing with a dart isolate. There's a little difference in how it gets set-up, and the streams are a bit simpler than python Queue's, but in general the idea is the same.
Basically:
Create a port to receive data from the isolate
Create the isolate passing it the port it will send data back on
Within the isolate, create the port it will listen on, and send the other end of it back to main (so main can send messages)
Determine and implement a simple messaging protocol for remote method call on an object contained within the isolate.
This is basically duplicating what a multiprocessing.Manager class does, however it can be helpful to have a simplified example of how it can work:
from multiprocessing import Process, Lock, Queue
from time import sleep
class HeavyObject:
def __init__(self, x):
self._x = x
sleep(5) #heavy init
def heavy_method(self, y):
sleep(.2) #medium weight method
return self._x + y
def HO_server(in_q, out_q):
ho = HeavyObject(5)
#msg format for remote method call: ("method_name", (arg1, arg2, ...), {"kwarg1": 1, "kwarg2": 2, ...})
#pass None to exit worker cleanly
for msg in iter(in_q.get, None): #get a remote call message from the queue
out_q.put(getattr(ho, msg[0])(*msg[1], **msg[2])) #call the method with the args, and put the result back on the queue
class RMC_helper: #remote method caller for convienience
def __init__(self, in_queue, out_queue, lock):
self.in_q = in_queue
self.out_q = out_queue
self.l = lock
self.method = None
def __call__(self, *args, **kwargs):
if self.method is None:
raise Exception("no method to call")
with self.l: #isolate access to queue so results don't pile up and get popped off in possibly wrong order
print("put to queue: ", (self.method, args, kwargs))
self.in_q.put((self.method, args, kwargs))
return self.out_q.get()
def __getattr__(self, name):
if not name.startswith("__"):
self.method = name
return self
else:
super().__getattr__(name)
def child_worker(remote):
print("child", remote.heavy_method(5)) #prints 10
sleep(3) #child works on something else
print("child", remote.heavy_method(2)) #prints 7
if __name__ == "__main__":
in_queue = Queue()
out_queue = Queue()
lock = Lock() #lock is used as to not confuse which reply goes to which request
remote = RMC_helper(in_queue, out_queue, lock)
Server = Process(target=HO_server, args=(in_queue, out_queue))
Server.start()
Worker = Process(target=child_worker, args=(remote, ))
Worker.start()
print("main", remote.heavy_method(3)) #this will *probably* start first due to startup time of child
Worker.join()
with lock:
in_queue.put(None)
Server.join()
print("done")

Thread is blocked in django - Python

the last 4 hours I have been trying to understand threading with django. Nothing seems to work. I want to let the website run in the foreground and let the backend communicate with some other devices on a thread. I want the thread to start at the startup of the website but the program is stuck when I call the thread until the thread comes to an end.
Do you know a way to fix it? Please I need help.
The urls.py file
def add(x, y):
i=0
while i < 100000000:
x += y
i += 1
def postpone(function):
t = threading.Thread(target=function, args=(1,))
t.setDaemon(True)
t.start()
return 0
print("Before thread")
postpone(add(4,4))
print("After thread")
The server will not start until the while loop is finished.
Thanks for reading, I hope someone knows an answer.
add function is called before the thread started, you need to pass add as reference though.
# decomposition
# first, add gets called
r = add(4,4)
# then the result is passed to func `postpone`
postpone(r)
# postpone accept a function and args, which eventually get passed to the function
def postpone(function, *args):
t = threading.Thread(target=function, args=args)
t.setDaemon(True)
t.start()
return 0
print("Before thread")
# pass func as a reference, also send args to the postpone func also
postpone(add, 4,4)
print("After thread")

Stop all threads using threading.Event()

I am creating a multiple threads to execute a function that generates PDF. This process takes a lot of time, so the user has a choice to cancel the execution.
To stop a thread, I know that I can use threading.Event() to check if it will be set. However, the process of the function I am executing in my event loop is straight forward/linear (There is no loop to check regularly if the Event is set).
--threading class--
def execute_function(self, function_to_execute, total_executions, execution_time, controller):
self.event = threading.Event()
self.event_list.append(self.event)
self.loop = asyncio.get_event_loop()
self.future = self.loop.run_in_executor(self._executor, function_to_execute, self.event, total_executions,
execution_time, controller)
def stop_executor(self):
for event in self.event_list:
event.set()
self.event = None
if self._executor:
self._executor.shutdown(wait=False)
def *function_to_execute*(self, event, total_execution, seconds=SECONDS_DEFAULT, controller=None):
self.event = event
self.controller = controller
...
My problem is that, I can't implement the Event to interrupt the threads without looping to regularly check the Event.
Is there any other way around to stop all those threads?
Or if I will still use the Event, is there any other logic to implement it?
Thanks in advance!

Resources