Working with Gtk a bit more lately, I found myself in need of non-blocking sockets. You can't easily use the
socket module in Python Gtk programs because they will either be blocking, or you'll have to write a lot of glue to use them with GLib's event loop in a non-blocking fashion.
The GNOME project provides a socket abstraction library called Gio. This library interacts well with GLib (and thus Gtk), and allows you to perform asynchronous reads and writes on sockets.
However, I couldn't find an example of how to use Gio in Python, so I thought I'd provide a working example here.
The following example asynchonously connects to a UNIX socket, writes given bytes to the socket synchronously, then reads from the socket until close and fires a given callback with the response.
from io import BytesIO from gi.repository import Gio, GLib def message_client(bytes, callback): request_id = next(request_counter) addr = Gio.UnixSocketAddress.new('/path/to/unix-socket') client = Gio.SocketClient.new() buf = io.BytesIO() def connect_callback(obj, result, user_data): conn = client.connect_finish(result) ostream = conn.get_output_stream() # FIXME: could also be async for super async ostream.write_bytes(GLib.Bytes(r)) istream = conn.get_input_stream() istream.read_bytes_async(8192, 1, None, read_callback, conn) def read_callback(obj, result, conn): istream = conn.get_input_stream() bytes = istream.read_bytes_finish(result) if not bytes.get_data(): conn.close(None) response = buf.getvalue() if callback is not None: callback(response) else: buf.write(bytes.get_data()) istream.read_bytes_async(8192, 1, None, read_callback, conn) client.connect_async(addr, None, connect_callback, None)
If you want to connect to a TCP server rather than a UNIX server, replace the
addr line above with the following:
addr = Gio.InetSocketAddress.new_from_string('127.0.0.1', 1234)