Message Dialog from outside the main gui thread

python blue and yellow logoIf you’ve ever wanted to show a dialog from a gtk app, but needed wanted to do it from outside the main thread, you quickly run into problems. Spawning things in gobject idle loops is usually fine for getting gui updates to happen in the main thread, but running a full blown dialog is not one of these easy feats.

So here’s a simple standalone program that fetches the dialog’s title and message before displaying it. You can also specify an image file path and icon size to override the default message info dialog icon.

From your worker thread, launch it using subprocess, system, or whatever you want, and immediately write the fields to it’s standard input. To simulate the usual dialog.run followed by dialog.destroy blocking behavior where you’re waiting for the user to close the dialog, just wait for the process to complete, die, or check its pid if you really don’t trust your io pipes. The side bonus is it’s not blocking if you just spawn it asynchronously and you will know the cleanup is handled since the dialog is not a part of your calling process other than the handle you create for spawning it.

import gtk
import sys

# read stdin lines for data
title = sys.stdin.readline().strip() # Dialog Title
msg = sys.stdin.readline().strip()  # Dialog Label
img = sys.stdin.readline().strip() # Dialog Image Filename
size = int(sys.stdin.readline().strip()) # Desired image pixel size

# create dialog
dialog = gtk.MessageDialog(None, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, msg)
dialog.set_title(title)
dialog.set_keep_above(True)

# override default dialog icon
try:
    pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(img, size, size)
    image = gtk.Image()
    image.set_from_pixbuf(pixbuf)
    image.show()
    dialog.set_image(image)
except:
    pass

# run
response = dialog.run()
sys.exit(0)

Dirty hack or part of the ingenious gtk masterplan?

Binary Buffers and Python Array Performance

Pre-allocate and Re-use for Performance

shipping containerWorking with binary packed data is typically used for high performance situations or passing data in/out of extensions. You can optimize by avoiding the overhead of allocating a new python array for each structure. The pack_into() and unpack_from() methods allow you to write to pre-allocated ctypes string buffers directly.

Here’s a common example of packing that I’ve fleshed out to include a few extra data types. You should probably use ctypes for the container whenever performance is critical, but the difference between python arrays and ctypes string_buffer doesn’t seem that bad for most cases.

#!/usr/bin/python -Ott
import array
import ctypes
import struct
import binascii

s = struct.Struct('c ? I f s')
values = ('z', True, 4, 2.54, 'word')
print 'ctypes.string_buffer:'

b = ctypes.create_string_buffer(s.size)
print 'Before packing  :', binascii.hexlify(b.raw)

s.pack_into(b, 0, *values)
print 'After packing  :', binascii.hexlify(b.raw)
print 'Unpacked:', s.unpack_from(b, 0)
print 'array:'

a = array.array('c', '\0' * s.size)
print 'Before packing :', binascii.hexlify(a)

s.pack_into(a, 0, *values)
print 'After packing  :', binascii.hexlify(a)
print 'Unpacked:', s.unpack_from(a, 0)

Performance Testing:

I tested both buffer types by looping through and filling a python array and a ctypes string_buffer using pack_into and unpack_from 250,000 times with an incremental double. It’s a silly example usage, but the python array took a little over 25 seconds to fill, while the ctypes took 22 seconds.

For comparison, I also testing with reallocation of the array on each iteration of the loop. The total time jumped up to a minute and a half.

A more specific example:

Binaries used for decoding on two ends of a messaging interface can convey a lot of information and is quite a bit more efficient than sending structures full of other larger things like more arrays, doubles, etc. The payload of a binary buffer saves a lot in terms of bandwidth when you’re sending messages very frequently.

And besides, you can’t always control the incoming data type when you need to talk to another piece of code through a messaging interface.

Write simple netsnmp apps in Python

Here’s a couple of different ways you can use netsnmp in Python.

I had a hard time finding documentation, and what I did find was old and outdated. I figured most of it out just by playing around with the library.

#!/usr/bin/env python
import netsnmp

string = 'public'
ver = 1
port = 161
host = '192.168.1.1'

# uptime using method 1
bind1 = netsnmp.Varbind('sysUpTime.0')
# 1 minute load using method 2
bind2 = netsnmp.Varbind('.1.3.6.1.4.1.2021.10.1.3.1')

snmpget = netsnmp.snmpget(bind1,
                    Version=ver,
                    RemotePort=port,
                    DestHost=host,
                    Community=string)
uptime_seconds = snmpget[0]
print uptime_seconds

list = ( bind1, bind2 )
x = netsnmp.Session(DestHost=host,
                    Version=ver,
                    RemotePort=port,
                    Timeout=400000,
                    Retries=5,
                    Community=string)
output_list = x.get(list)
if not output_list:
    print "FAILED TO CONNECT!!!"
    sys.exit(1)

if output_list[0]:
    uptime = output_list[0]

if output_list[1]:
    load1 = output_list[1]

python blue and yellow logoNext I wrote a class to wrap it up as an AWN applet. If you’ve never heard of AWN or haven’t tried the avant-window-navigator you should definitely check it out and consider continuing development on it. It was the best app bar available; very pretty. It fit my needs at the time anyway.

I replaced the bottom gnome-panel with it. If you remove everything except the Launcher/Taskmanager applet and add the Show Desktop applet, it directly replaces gnome-panels functionality completely.