No Python switch statement?

Posted February 20th, 2011 in Python by James

When I was relatively new to Python and writing my first real program, one of the first things I noticed was the lack of a switch statement, which had become commonplace when coding in Java.

Since then I’ve found multiple ways to achieve the same effect (without the use of if-else’s!);

Firstly the concept of assigning a variable using a switch, which in Java may look something like this;

1
2
3
4
5
6
7
8
9
10
11
  int result;
  switch(condition)
   {
     case 'a': result = 1; 
       break;
     case 'b': result = 2; 
       break;
     case 'c': result = 3;  
       break
     default: result = 0;
   }

We can achieve the same in Python using a dictionary;

1
2
3
4
5
result = {
  'a': 1,
  'b': 2,
  'c': 3
}[condition]

And lets say we want to define functions as the result of our switch. Also you may have noticed that the above does not define a default action, which is present in the Java equivalent. We can include both like so;

1
2
3
4
5
6
7
8
# define the dict
values = { 
           'a': do_stuff, 
           'b': do_stuff2, 
           'c': do_stuff3,
 }
# get the function
values.get(condition, do_default)()

This will execute the do_stuff function defined by the condition, and if a value is not found then it will execute do_default.

Much less verbose wouldn’t you say?

I have one more to add to the list, which I guess is really Reflection, but can be used for the same purpose and is pretty cool in Python.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
method_name = 'do_' + condition
if not hasattr(self, method_name):
   do_default
else:
   method = getattr(self, method_name)
   result = method()
 
def do_a:
  return 1
def do_b:
  return 2
def do_c:
  return 3
def do_default:
  return 0

Some explanation may be in order if you’re not familiar with Python. If you’re a Java pro, then you may be used to fetching attributes or methods using the getClass() function. This is much easier and awesome in Python.

To put it bluntly, the built in function hasattr checks the object’s (in this case ‘self’) attributes for the given string.
Then we use getattr to retrieve the attribute, in this case a function, which is then executed.

There you have it. As you see, these examples of switch statements provide much more flexibility (mainly in the fact that you are not limited to primitive types!), and are in most cases much less verbose.
Happy coding!

Grab UI window text with Python

Posted November 29th, 2010 in Java, Python by James

I just discovered this old piece of code while digging through ancient e-mails. which I was quite pleased about since I thought it had been lost.

I wrote it to perform the simple function of getting text from an open window in XP, though I assume it would work for other Windows versions.
I had been writing a Java program which required text from the output of a native Windows application. And although this could probably better be achieved in a different language, I thought that integrating Python output into a Java application would be fairly trivial.

I achieved it by simply using Runtime and Process objects.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
final String pythonDir = "cmd /c pythonFile.py";
final Runtime r  = Runtime.getRuntime();
 
//run python process
try
{
   Process p = r.exec(pythonDir);
   BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()), 5000);
 
   //while there is text, read.
   while ((line = br.readLine()) != null)
   {
     //parse each line
   }
}
catch (Exception e)
{ }
// done

However, from what I remember it was the Python that proved exceptionally difficult, mainly due to terrible documentation, and from some Googling I can see I’m not the only one to have found this problem. Now at least it does seem to have gotten better, though probably it’s easier to find now that I know what to search for.

Nevertheless, I managed to hack together workable code to find a specific open window based on the Title bar text, and grab text from that window.
Though it is probably not the most elegant or fastest solution, it worked and I was able to read the window text output into my Java application perfectly.

I can’t remember enough to document my code line by line, but I think from the comments it should be quite straightforward…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import win32con
import win32gui
import array
import ctypes
import struct
import sys
import win32api
from ctypes import *
 
results = []
topWindows = []
chatHwnd = 0
windowTitleText = "Window Title"
#The text that the wanted window string begins with, so we can find it
windowStartText = "Welcome"
 
 
if __name__ == '__main__':
    #declare global
    global chatHwnd
    #enumerate all open windows, return topWindows
    win32gui.EnumWindows(_windowEnumerationHandler, topWindows)
    #check each window to fin the one we need
    for hwnd, windowText, windowClass in topWindows:
    if windowText.find(windowTitleText)>-1:
            #search the child windows
            # save the window handle
            chatHwnd = searchChildWindows(hwnd)
            #set the appropriate window focus (if needed)
            win32gui.SetFocus(hwnd)
            win32gui.SetForegroundWindow(hwnd)
 
            initBuff = 0
            #get text
            while chatHwnd>0:
 
                buf_size = 1 + win32gui.SendMessage(chatHwnd, win32con.WM_GETTEXTLENGTH, 0, 0)
                buffer = win32gui.PyMakeBuffer(buf_size)
                # send a win GETTEXT request to the window and read into buffer
                win32gui.SendMessage(chatHwnd, win32con.WM_GETTEXT, buf_size, buffer)
                if buf_size-initBuff>1:
                      print buffer[initBuff:buf_size]
 
                initBuff = buf_size
                #after 5 seconds, get any new text
                time.sleep(5)
                # needed for Java to read the output correctly
                sys.stdout.flush()
 
 
'''Handler to enumerate the window with param hwnd
Returns resultsList; the window details as an array,
with hwnd, text and class'''
def _windowEnumerationHandler(hwnd, resultList):
    resultList.append((hwnd,
                       win32gui.GetWindowText(hwnd),
                       win32gui.GetClassName(hwnd)))
 
'''Recursive function, checks the text of all the children of
the window with handle param hwnd until it reaches the text that
we require, returns the String of this data'''
def searchChildWindows(hwnd):
childWindows = []
    try:
        #get child windows
        win32gui.EnumChildWindows(hwnd, _windowEnumerationHandler, childWindows)
    except win32gui.error, exception:
        # This seems to mean that the control does not or cannot have child windows
        return
 
    #get details of each child window
    for childHwnd, windowText, windowClass in childWindows:
        #create text buffer
        buf_size = 1 + win32gui.SendMessage(childHwnd, win32con.WM_GETTEXTLENGTH, 0, 0)
        buffer = win32gui.PyMakeBuffer(buf_size)
        #get text from Window using hardware call. (getWindowText() did not return anything)
        win32gui.SendMessage(childHwnd, win32con.WM_GETTEXT, buf_size, buffer)
        #check to see if it's the data we want...
        if buffer[0:buf_size].find(windowStartText)>-1:
            #return the hwnd
 
            #global chatHwnd
            #chatHwnd = childHwnd
            return int(childHwnd)
        #else recurse, checking this window for children
        #might not be needed...
        #searchChildWindows(childHwnd)

And there we are, I hope this is able to save someone else all the time that it cost me.