Tuesday, 8 September 2009

Testing HTTP using Telnet

While this is commonplace knowledge, I find myself googling for it every time I need to test HTTP connectivity and responses with telnet. Telnet provides a quick and dirty means to put back data over HTTP and to test the response headers.

Firstly, fire up telnet with the hostname and port for the HTTP connection:
telnet www.somesite.com 80
If it can connect to the server, then you will be presented with:

Trying www.somesite.com...
Connected to www.somesite.com.
Escape character is '^]'.

Now type the following to request index.html over HTTP:

GET /index.html HTTP/1.1
host: www.somesite.com

This will then return the header information, followed by the actual data.

Wednesday, 26 November 2008

Tree'd by XML

The standard python distribution comes with a plethora of XML support modules: the usual SAX and DOM parsers, a lightweight minidom, wrappers for the Expat parser and something called ElementTree. While Expat seems to get a lot of attention, I recently tried the ElementTree way of doing things and was very pleasanlty surprised.

ElementTree treats XML documents as a hierarchy of containers, which behave in much the same way as lists or dictionaries. Every node in an XML document is represented as an Element, with elements as sub-elements of their parent.

So, for example, let's declare a root with some sub-nodes:

book = Element('Book')
title = SubElement(book, 'Name')
SubElement(book, 'Title')

To turn this into a valid XML document, just use the tostring(book) function, or write it to a file with the ElementTree().write() method.

Want to add text to an element/node? Just use title.text = 'Bookishness'. To add attributes, again simplicity: title.attrib['binding'] = 'hardback'. Accessing attributes is a case of: book.get('binding').

Now, to get all pythonic on ElementTree, here's how to create a (sub)node, add attributes and text all in one line:

SubElement(book, 'Author', sex='Female', nationality='British').text = 'JK Rowling'

More concise than a Harry Potter doorstop.

Tuesday, 25 November 2008

Dictionary in love

Merging two dictionaries. It should be easy and it is. Just use the update() method of one of the dictionaries:

d1 = { 'a': 1, 'b': 2}
d2 = {'b': 2, 'c': 3}
d1.update(d2)

d1 is now {'a': 1, 'c': 3, 'b': 2}

But often I don't want to transform one of dictionaries, I want to create a third from the combination of the two. I could make a deep copy of one of the dictionaries and update that (badness), or go through the items and merge (more badness).

And here is where dict() comes to the rescue once again:

d3 = dict(d1, **d2)

That's it; merged -- and it's pretty damn fast too.

Hey man, nice shot .. aka filter

Filter is another of those incredibly handy built-in python functions. It takes a function and a list, and filters the elements of the list using the function:

filter(f, a)

So say we want to filter out all those pesky Nones from a list where Nones have no right to be: [1, None, 2, 3, None, 4]. We could go down the iterate through the list, creating a new list from all the non-null elements ... but that requires multiple lines of tedium.

Instead we employ the power of filter() and -- wait for it -- a lambda function!

filter(lambda x: x != None, [1, None, 2, 3, None, 4])

And presto! The Nones are no more.

Writing a dictionary like Dr. Johnson

Typically when I used create a dictionary of elements, I employed the tried and true method declaration followed by element addition:

d = {}
d['a'] = 1
d['b'] = 2
...

Now I find I favour a slightly more compact and pythonic means, using the built-in dict() function:

d = dict( a = 1, b = 2, ... )

Both render the same dictionary:

{'a': 1, 'b': 2 ... }

Last element standing

To access the last element in a list, there's no need for the long-winded list[len(list) - 1].

All that's needed is list[-1].

Monday, 24 November 2008

List of strings, or not list of strings ...

Following on from the nifty ', '.join(l) time-(and sanity-) saver, here's the answer to the Oh no! it's a list of strings and not some other random objects that I need! disaster.

The problem is simple: I have a list of non-string objects, but the operation I want to perform on them requires a list of strings. Naively I break out the dreaded conversion loop:

num_list = [1, 2, 3, 4]
str_list = []
for item in num_list:
str_list.append( str(item) )

Bah! Three lines of code! Whatta waste!

Python to the rescue with the line-saving map function:

map(str, num_list)

And we're done.

The map function takes a function and a list, and applies that function to each element of the list, so it is useful for much more than just string magic.

So, to print the list of ints above, separated by commas:

', '.join( map(str, num_list) )