I have a background process started, but I have no idea how to stop the process. I've read through the documentation but there doesn't seem to be any built in function to kill the task. How should I resolve this? I am specifically referring to the stopCollectingLiveData() section.
#socketio.on('collectLiveData')
def collectLiveData():
global thread
with thread_lock:
if thread is None:
thread = socketio.start_background_task(background_thread)
def background_thread():
"""Example of how to send server generated events to clients."""
count = 0
while True:
socketio.sleep(1)
count += 1
socketio.emit('my_response', {'count': count})
#socketio.on("stopCollectingLiveData")
def stopCollectingLiveData():
print('')
socketio.sleep()
You can stop the background thread with an event object, which you can pass as a parameter. As long as the event is set, the thread runs. When the event is cleared, the thread's execution is suspended.
# ...
from threading import Event
thread_event = Event()
# ...
#socketio.on('collectLiveData')
def collectLiveData():
global thread
with thread_lock:
if thread is None:
thread_event.set()
thread = socketio.start_background_task(background_thread, thread_event)
def background_thread(event):
"""Example of how to send server generated events to clients."""
global thread
count = 0
try:
while event.is_set():
socketio.sleep(1)
count += 1
socketio.emit('my_response', {'count': count})
finally:
event.clear()
thread = None
#socketio.on("stopCollectingLiveData")
def stopCollectingLiveData():
global thread
thread_event.clear()
with thread_lock:
if thread is not None:
thread.join()
thread = None
Related
I am trying to make use of Windows Hooks in order to intercept and block keystrokes while my application sends its own gui events.
I came up with the following listing:
import pythoncom
import pyHook
import threading
import time
def on_keyboard_event(event):
print 'MessageName:',event.MessageName
print 'Message:',event.Message
print 'Time:',event.Time
print 'Window:',event.Window
print 'WindowName:',event.WindowName
print 'Ascii:', event.Ascii, chr(event.Ascii)
print 'Key:', event.Key
print 'KeyID:', event.KeyID
print 'ScanCode:', event.ScanCode
print 'Extended:', event.Extended
print 'Injected:', event.Injected
print 'Alt', event.Alt
print 'Transition', event.Transition
print '---'
return False
class WindowsHooksWrapper:
def __init__(self):
self.started = False
self.thread = threading.Thread(target=self.thread_proc)
self.hook_manager = pyHook.HookManager()
def start(self):
if self.started:
self.stop()
# Register hook
self.hook_manager.KeyDown = on_keyboard_event
self.hook_manager.KeyUp = on_keyboard_event
self.hook_manager.HookKeyboard()
# Start the windows message pump
self.started = True
self.thread.start()
def stop(self):
if not self.started:
return
self.started = False
self.thread.join()
self.hook_manager.UnhookKeyboard()
def thread_proc(self):
print "Thread started"
while self.started:
pythoncom.PumpWaitingMessages()
print "Thread exiting..."
class WindowsHooksWrapper2:
def __init__(self):
self.started = False
self.thread = threading.Thread(target=self.thread_proc)
def start(self):
if self.started:
self.stop()
self.started = True
self.thread.start()
def stop(self):
if not self.started:
return
self.started = False
self.thread.join()
def thread_proc(self):
print "Thread started"
# Evidently, the hook must be registered on the same thread with the windows msg pump or
# it will not work and no indication of error is seen
# Also note that for exception safety, when the hook manager goes out of scope, it
# unregisters all outstanding hooks
hook_manager = pyHook.HookManager()
hook_manager.KeyDown = on_keyboard_event
hook_manager.KeyUp = on_keyboard_event
hook_manager.HookKeyboard()
while self.started:
pythoncom.PumpWaitingMessages()
print "Thread exiting..."
self.hook_manager.UnhookKeyboard()
def main():
# hook_manager = pyHook.HookManager()
# hook_manager.KeyDown = on_keyboard_event
# hook_manager.KeyUp = on_keyboard_event
# hook_manager.HookKeyboard()
# pythoncom.PumpMessages()
hook_wrapper = WindowsHooksWrapper2()
hook_wrapper.start()
time.sleep(30)
hook_wrapper.stop()
if __name__ == "__main__":
main()
The commented out section in main was from the pyhook wiki tutorial and it works fine.
I then tried to integrate that into a class, which is the 'WindowsHooksWrapper' class. If I used that class, it does not work and keyboard messages go through to their intended target.
On a hunch, I then tried 'WindowsHooksWrapper2', where I moved the registration of the hook to the same thread with the message pump. It now works.
Is my hunch correct that it is a requirement for the registration to be on the same thread as the pump? If so, why?
Note that I have a feeling this is a requirement of the windows 32 API rather than python or the pyhook library itself, because I did it in C++ and had the same result using 'SetWindowsHook' directly.
You've created a thread-Scope hook.
These hook events are associated either with a specific thread or with all threads in the same desktop as the calling thread.
pythoncom.PumpWaitingMessages() in Python and GetMessage/PeekMessage in Win32 are the methods that get message from that "specific thread or all threads in the same desktop as the calling thread."
To create a global hook, in order for your keyboard hook to be accessible from all processes, it has to be placed in a DLL which will then be loaded into each process' address space. See this Answer for details of how to make a global keyboard hook.
I'm trying to implement a concurrent dictionary in Python - more specifically, the dictionary would be used by two threads, one that would use its clear and update methods, and the other which would access its values directly (i.e., by its __getitem__ method). The implementation is below:
from threading import Lock, current_thread
class ThreadSafeDict(dict):
def __init__(self, *args, **kwargs):
self._lock = Lock()
super(ThreadSafeDict, self).__init__(*args, **kwargs)
def clear(self, *args, **kwargs):
print("thread {} acquiring clear lock".format(current_thread().ident))
self._lock.acquire()
print("thread {} acquired clear lock".format(current_thread().ident))
super(ThreadSafeDict, self).clear(*args, **kwargs)
print("thread {} releasing clear lock".format(current_thread().ident))
self._lock.release()
print("thread {} released clear lock".format(current_thread().ident))
def __getitem__(self, *args, **kwargs):
print("thread {} acquiring getitem lock".format(current_thread().ident))
self._lock.acquire()
print("thread {} acquired getitem lock".format(current_thread().ident))
val = super(ThreadSafeDict, self).__getitem__(*args, **kwargs)
print("thread {} releasing getitem lock".format(current_thread().ident))
self._lock.release()
print("thread {} released getitem lock".format(current_thread().ident))
return val
def update(self, *args, **kwargs):
print("thread {} acquiring update lock".format(current_thread().ident))
self._lock.acquire()
print("thread {} acquiring update lock".format(current_thread().ident))
super(ThreadSafeDict, self).update(*args, **kwargs)
print("thread {} releasing update lock".format(current_thread().ident))
self._lock.release()
print("thread {} released update lock".format(current_thread().ident))
I'm testing the implementation with this script:
import threading
import random
import time
from threadsafedict import ThreadSafeDict
def reader(tsd):
while True:
try:
val = tsd[1]
except KeyError:
pass
interval = random.random() / 2
time.sleep(interval)
def writer(tsd):
while True:
tsd.clear()
interval = random.random() / 2
time.sleep(interval)
tsd.update({1: 'success'})
def main():
tsd = ThreadSafeDict()
w_worker = threading.Thread(target=writer, args=(tsd,))
r_worker = threading.Thread(target=reader, args=(tsd,))
w_worker.start()
r_worker.start()
w_worker.join()
r_worker.join()
if __name__ == '__main__':
main()
Sample output:
thread 140536098629376 acquiring clear lock
thread 140536098629376 acquired clear lock
thread 140536098629376 releasing clear lock
thread 140536098629376 released clear lock
thread 140536090236672 acquiring getitem lock
thread 140536090236672 acquired getitem lock
thread 140536090236672 acquiring getitem lock
thread 140536098629376 acquiring update lock
What am I doing wrong?
(I realize this concurrency would already be safe in CPython, but I'm trying to be implementation-agnostic)
The problem is that when the super().__getitem__() call in your ThreadSafeDict.__getitem()__ method fails to find an item with the given key, it raises KeyError which causes the remainder of your __getitem__() method to be skipped. That means that the lock will not be released, and any later calls to any of your methods will be blocked forever waiting to obtain a lock that will never be unlocked.
You can see that this is happening by the absence of 'releasing' and 'released' messages after the 'acquired getitem lock' message, which is immediately followed in that excerpt by another attempt to acquire the lock by the read thread. In your test code, your read thread will always hit this condition if it runs in the interval after a clear() has been performed but before an update() has been performed by the write thread.
To fix, catch the KeyError exception in your __getitem__() method, then release the lock, then re-raise the exception. The 'try/finally' construct provides a very straightforward way to do this; in fact this is the perfect situation for the use of 'finally'.
Or you could check that the desired key exists after acquiring the lock and before before calling super().__getitem__(), although that will hurt performance slightly if the usual expectation is that the key will exist.
BTW, it's not a great idea to have your ThreadSafeDict inherit from the dict class. This causes ThreadSafeDict to inherit all of the dict methods (for instance, __setitem__()) and any of those methods that you haven't overridden would bypass your lock if someone used them. If you aren't prepared to override all of those methods then it would be safer to have the underlying dict be an instance member of your class.
My python project has multiple threads running. I want to add a gauge widget from the wxpython library to show the progress. I want the gauge to fill until my first thread completes. How do I achieve this? I am using Python 2.7 on Windows.
Use wx.CallAfter
def add_to_the_gauge(value):
your_gauge.Value += value
...
#in some thread
def some_thread_running():
wx.CallAfter(add_to_the_gauge, 2)
You need to post events from your worker thread to the main thread asking it to update the gauge, see this overview.
You can use some simple things
remember to import the module:
import os
and then put this on the frame
def __init__(self, *a, **k):
filename = 'game.exe'
self.timer = wx.Timer()
self.Bind(wx.EVT_TIMER, self.OnUpdateGauge, self.timer)
self.timer.Start()
self.proc = os.popen(filename) # start the process
def OnUpdateGauge(self, event):
if self.proc.poll() == None: # return None if still running and 0 if stopped
self.timer.Stop()
return
else:
'''do something with the gauge'''
hope those help
Hi I'm new to python and have started developing a GUI using wxpython. I just want to know the basic threading operation in wxpython. I have a main process which has OK & Cancel Buttons and a child process derived from main with the OK and Cancel Buttons. I want to implement threading such a way that clicking OK button on main process must send a message to child process and child process must look for if any of it's process is running, if so, it has to wait for that process to finish and then receive the message from main process.Similarly the same with the Cancel button in the main process.
Basically i want to see how child process receives message from main process and both work parallel.
I'm trying with wx.CallAfter and wx.PostEvent and i'm confused with the threading concept here. Please someone help me.
Thanks in advance
Multithreading in wxpython is not different than in python. wx.CallAfter and threading example shows how you use both. wx.CallAfter waits for the event to be completed and run the handler in the main thread. Additionally, you can use timers (wx.Timer) to check child processes and send/receive data.
Here is a link for wx.PostEvent showing how to use it. In this example, you create custom event, bind it to a handler in main thread. After that you post the event in a worker thread and attach some data as well. Your event handler receives the event and do some stuff in the main thread.
So, there are important questions arising when you use multithreading
When to start the child threads,
Which communication mechanism is used between threads,
How to stop the threads in a safe way when necessary,
etc.
I would prefer wx.Timer + Queue module. I can regularly check the queue with timers or with user events and send something (i.e. None) through queue to stop threads.
Note: Long running jobs in main thread can make GUI unresponsive.
I got it right. THanks to #ozy
import threading
import wx
from threading import Thread
ID_RUN = 101
ID_RUN2 = 102
class ChildThread(Thread):
def __init__(self, myframe):
"""Init Worker Thread Class."""
Thread.__init__(self)
self.myframe = myframe
def run(self):
wx.CallAfter(self.myframe.AfterRun, 'Ok button pressed')
class MyFrame(wx.Frame):
def __init__(self, parent, ID, title):
wx.Frame.__init__(self, parent, ID, title)
panel = wx.Panel(self, -1)
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
mainSizer.Add(wx.Button(panel, ID_RUN, "OK"))
mainSizer.Add(wx.Button(panel, ID_RUN2, "Cancel"))
panel.SetSizer(mainSizer)
mainSizer.Fit(self)
wx.EVT_BUTTON(self, ID_RUN, self.onRun)
wx.EVT_BUTTON(self, ID_RUN2, self.onRun2)
def onRun(self, event):
self.child = ChildThread(myframe=self)
self.child.daemon = True
self.child.start()
def onRun2(self, event):
self.child2 = threading.Thread(None, self.__run)
self.child2.daemon = True
self.child2.start()
def __run(self):
wx.CallAfter(self.AfterRun, "Cancel button pressed")
def AfterRun(self, msg):
dlg = wx.MessageDialog(self, msg, "Message", wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, "My GUI")
frame.Show(True)
frame.Centre()
return True
app = MyApp(0)
app.MainLoop()
I am trying to build a basic messaging system, but I have hit a major roadblock in the process. I can't get the window to close without it not responding and me having to close it in the Task Manager. From what I've read online, it sounds like I need to close when a sys.exit(0) to exit all the threads and connections. I have been stuck on this problem for days so I would really appreciate an answer and explanation to why it doesn't work! The meat of the problem is in the close_window() function. It is run able provided you have a basic server that accepts a connection. Thanks!
import wx
import socket
import threading
import sys
class oranges(wx.Frame):
def __init__(self,parent,id):
##Unimportant stuff
wx.Frame.__init__(self,parent,id," Retro Message",size=(500,500))
self.frame=wx.Panel(self)
self.input_box=wx.TextCtrl(self.frame, -1,pos=(15,350),size=(455,120),style=wx.NO_BORDER| wx.TE_MULTILINE)
self.messaging_box=wx.TextCtrl(self.frame, -1,pos=(15,15),size=(455,285),style=wx.NO_BORDER | wx.TE_MULTILINE|wx.TE_READONLY)
send_button=wx.Button(self.frame,label="Send",pos=(350,315),size=(75,40))
self.Bind(wx.EVT_BUTTON, self.sender,send_button)
self.Bind(wx.EVT_CLOSE, self.close_window)
self.counter = 1
self.socket_connect = socket.socket()
self.setup()
def sender(self,event):
self.socket_connect.send(self.input_box.GetValue())
self.input_box.Clear()
self.Refresh()
##Important stuff
def close_window(self,event): #This is the function in question#
self.counter = 0
self.socket_connect.shutdown(socket.SHUT_RDWR)
sys.exit(0)
def setup(self):
self.ip_enter = wx.TextEntryDialog(None, "Enter in the IP:", "Setup", "192.168.1.1")
if self.ip_enter.ShowModal() ==wx.ID_OK:
self.offical_ip = self.ip_enter.GetValue()
try:
self.socket_connect.connect((self.offical_ip,5003))
self.username = "false" #Tells the server just to give the user a IP username
self.Thread1 = threading.Thread(target = self.listening_connect)
self.Thread1.start()
except socket.error:
self.error_connect()
else:
sys.exit(0)
def listening_connect(self):
self.socket_connect.send(self.username)
while self.counter != 0:
data = self.socket_connect.recv(1024)
self.messaging_box.AppendText(data)
self.Refresh()
if not data:
break
self.socket_connect.close()
def error_connect(self):
pop_ups = wx.MessageDialog(None, "Failed to Connect to Server!", 'Error', wx.OK)
pop_ups.ShowModal()
self.setup()
if __name__=="__main__":
app=wx.App(False)
window=oranges(parent=None,id=-1)
window.Show()
app.MainLoop()
Here is a basic server program that should work with it(I am unable to test it but it is very similar to the real one)
import socket
HOST = '192.168.1.1'
PORT=5003
s = socket.socket()
s.bind((HOST, PORT))
s.listen(1)
c,addr = s.accept()
while True:
data = c.recv(1024)
if not data:
break
c.close()
You need to wait for the thread to end. Otherwise it's probably going to make the script hang. Why? Well the thread is separate from the GUI thread, so it doesn't get killed just because you closed down your wxPython application. Here is what I would recommend:
def close_window(self, event):
self.Thread1.join()
self.Destroy()
This makes the script wait for the thread to finish before closing the application. If you want the frame to disappear, then you should call self.Hide() before the join. Another method would be to put some logic in your thread where you can send it a message that tells it the application is shutting down, so the thread needs to abort.
You should probably check out the following Stack answer:
Is there any way to kill a Thread in Python?