Use Thread in Pygtk - python

I'm in a project to develop a chat application like netmeeting. I want to separate thread one is for GUI (gtk.main) another is simultaneously accepting client chat request (socket.accept) . But there is a problem..
here is my simple line of code which is 2nd thread for accepting client request:
while True:
self.new_sock,self.client_addr = self.sock.accept()
#CloseDialog is a messege box
respons=self.CloseDialog.run()
if respons==gtk.RESPONSE_YES:
#Call a Chat Window
elif respons==gtk.RESPONSE_NO:
#Close the requested socket
when i run the application it switch to the gtk.main loop and my 2nd thread is unable to run. is there any process to run those thread parallel, But I'm very confuse to implement this. if you need any further information I will give it to you. Please help me..
thanks in advance

Have a look at PyGTK FAQ. In particular, I suggest the gobject.idle_add() approach. When your second thread needs any GUI interaction, schedule some code running in the main thread with `gobject.idle_add(), sort of like this:
def ask_close ():
self.CloseDialog.run ()
gobject.idle_add (ask_close)
Then you'd need to wait for some mutex X for when answer (in the main thread) arrives. I also recommend not using modal dialogs (run()), because that largely defeats the purpose of having multiple threads. Instead, use present() and connect a callback to response signal. This callback would release mutex X so that the second thread can stop waiting and process the answer.

Related

wxpython: How to pass XY coordinator and draw it out?

I'm new for python but willing to learn. I have a set of hardware to receive touch coordinators and draw line accordingly to coordinators.
My problem is that the wxpython won't draw line if coordinator changes.
Here is my code : https://github.com/eleghostliu/homework/blob/master/DrawXY_byWxPython/PythonApplication1/PythonApplication1.py
can someone give advise, thanks.
You registered for EVT_PAINT, yet you are not triggering the event as the data changes. The frame has no idea whether data changed or not, unless you specifically inform it.
You can trigger the event simply by calling
frame.Refresh()
You can hook it in several ways. For instance, you could pass frame.Refresh bound method as a parameter to MainProcess so that it can make the function call to refresh the frame. Something like the following:
WARNING: Erroneous code piece
# Start a socket server
def MainProcess(refresh_callback):
while True:
refresh_callback()
***********************************************
frame = DrawPanel()
frame.Show()
start_new_thread(MainProcess, (frame.Refresh,))
Edit:
The above code piece calling UI methods directly is wrong!
Worker thread should not directly manipulate GUI, instead it should inform the GUI thread about a change, and the GUI thread which is the main thread will handle it in its context. There are again several approaches here, the quickest to implement is through wx.CallAfter.
Which you can incorporate as below, instead of directly calling the function:
wx.CallAfter(refresh_callback)
Another way to handle the communication between worker thread and GUI thread is via wx.PostEvent.
class DrawPanel(wx.Frame):
"""Draw a line to a panel."""
def notify(self):
wx.PostEvent(self, wx.PaintEvent())
Then from the secondary thread, you can safely call frame.notify() whenever new data arrives.
For a more elegant solution involving wx.CallAfter, refer to https://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/ where pubsub is used.

python daemon server crashes during HTML popup overlay callback using asyncio websocket coroutines

My python daemon process stops working when its asyncio run_forever loop listens to websocket calls that originate from a separate run_until_complete asyncio coroutine (or thread) but runs within the same process (PID). More specifically, I code a localhost server in Python 3.4.3 that updates via the webbrowser function an HTML web page in my firefox webbrowser. I then try to capture button presses elicited in a temporary popup window overlay and relay the associated action strings via websocket calls back to the daemonized server.
Things work fine and calls are processed flawlessly in the websocket server embedded in the run_for_ever asyncio loop when the websocket client call comes from an independent non-demonized PID invoked via a command-line call to the same python script. Things also work fine for the websocket server when an HTML-GUI-based websocket call hits the run_for_ever asyncio loop. But things go wrong when an initial asyncio coroutine process requires additional user-input - through a locking HTML window overlay and buttons such as 'accept', 'cancel' or 'quit' - and thereby attempts to capture the button press related websocket string signal through a brief separate run_until_complete asyncio coroutine.
In other words, I try to find a way to control flow through my Python script where intermittently a webbrowser-GUI user-input is required to influence program logic. How can that be achieved in a pure Python solution ?
ok, I found a solution for the problem described above, with two changes :
1) call_soon_threadsafe : this one finally 'isolates' my second asyncio loop so that the first asyncio loop survives when the following line gets invoked :
loop = asyncio.get_event_loop()
loop.call_soon_threadsafe( asyncio.async, websockets.serve( myFunct2, IP, PORT2))
loop.run_forever()
2) I use a separate number for PORT2 for the HTML popup overlay button websocket callback calls which corresponds with the second asyncio websocket loop (see above). In sum, regular GUI callbacks go with the PORT1 number, while the popup GUI calls go with the PORT2 number - for which the second asyncio websocket loop is created temporarily.

Python: Show message 'Waiting for player...' while socket listens for connection

Making a very simple tic-tac-toe game in Python using a P2P architecture with sockets. Currently my GUI has button that says 'Create' that will open up and draw a new game board window, create a socket, bind, listen, and accept a connection. The 'Join' button will open and draw a new gameboard and connect to that 'server'.
I'm trying to have it show a message saying 'Waiting for player...' when you create a game, a cancel button to stop and go back to the main menu, and have it disappear on it's own if a connection has been accepted.
I tried using tkMessageBox but the script stops until the user clears the message so there's no way for me to listen/accept until the user presses something.
What other way is there for me to accomplish this?
Thanks!
Sounds like a threading issue.
I'm unfamiliar with TK graphics, but I'd imagine what you need to do is start the window showing the "waiting for player" message. That window then loops waiting for something to happen.
When the message box displays you need to have the "listening" done on another thread, which signals back to the main message box when someone's connected using a semaphore or a queue.
On your main GUI thread you need to make the loop:
check the queue or semaphore for values. If there's a value on there that you expect, close the box. This would need to be non-blocking so that the GUI thread can still check for input from the user.
check for user input. That's probably done using callback functions though.

Signal handler accepts (*args), how do I provide them?

I'm using a library called BACpypes to communicate over network with a PLC. The short version here is that I need to start a BACpypes application in its own thread and then perform read/write to the plc in this separate thread.
For multiple PLC's, there is a processing loop that creates an application (providing the plc ip address), performs read writes on plc using application, kills application by calling BACpypes stop(*args) from the Core module, calls join on the thread, and then moves on to next ip address in the list until we start over again. This works for as many ip addresses (PLCs) as we have, but as soon as we are back at the first ip address (PLC) again, I get the error:
socket.error: [Errno 98] Address already in use
Here is the short code for my thread class, which uses the stop() and run() functions from BACpypes core.
class BACpypeThread(Thread):
def __init__(self, name):
Thread.__init__(self)
Thread.name = name
def run(self):
run()
def stop(self):
stop()
It seems like I'm not correctly killing the application. So, I know stop(*args) is registered as a signal handler according to BACpypes docs. Here is a snippet I pulled from this link http://bacpypes.sourceforge.net/modules/core.html
core.stop(*args)
Parameters: args – optional signal handler arguments
This function is called to stop a BACpypes application. It resets the running boolean value. This function also installed as a signal handler responding to the TERM signal so you can stop a background (deamon) process:
$ kill -TERM 12345
I feel like I need to provide a kill -term signal to make the ip address available again. I don't know how to do that. Here's my question...
1) In this example, 12345 is the process number I believe. How do I figure out that number for my thread?
2) Once I have the number, how do I actually pass the kill -TERM signal to the stop function? I just don't know how to actually write this line of code. So if someone could explain this that would be great.
Thanks for the help!
Before stopping the core, you need to free the socket.
I use :
try:
self.this_application.mux.directPort.handle_close()
except:
self.this_application.mux.broadcastPort.handle_close()
After that I call stop
then thread.join()

How to run separate threads in pygtk

I have a pygtk application which runs as soon as my python script is opened. Along with gtk.main() I have a thread which is started at the beginning of the script, which refreshes a gtk.TextView() instance:
def listen(self):
while True:
print "refreshing"
data = self.socket.recv(buffer_size)
if data:
self.txtBuffer.insert(self.txtBuffer.get_end_iter(), data + "\n")
print data
thread.start_new_thread(self.listen, ())
self.set_up_gui() # gtk.main()
However, when I run the program, the gui opens, but no "refreshing" text is printed, nor is any data printed when sent to the socket. I have attempted to use glib.add_idle() to thread this program, however that only runs the separate thread when the gui is idle (which is infrequent). Thank you!
You are accessing the text buffer from a different thread without any synchronization, which is unsupported. To fix that, replace self.txtBuffer.insert(...) with gobject.idle_add(lambda: self.txtBuffer.insert(...)). That tells the GUI thread to update the text buffer at the next main loop iteration, which is guaranteed to work without explicit synchronization.
You should make sure that the GUI thread is not blocked, i.e. that it's running gtk.main() and only processing GUI updates such as the above textBuffer.insert. Long-running/blocking tasks should be delegated to other threads or processes, as your code already tries to do. When this is implemented, GUI updates will appear to happen instantaneously.
See this answer for additional details on PyGTK and threading.

Categories