Thursday, August 20, 2009

Python 3.1 File I/O open() Is No Longer Binary Mode By Default

After long holiday on my wedding preparation, D day and honeymoon, I returned back in shape.

Some things happened during the off days, such as the acquisition of SpringSource by VMWare, Inc.

I try to run my piece of XML parsing code like this in Python 3.1:

[sourcecode lang="python"]
import xml.parsers.expat
import sys
import os.path

filename = "companies.xml"
parser = xml.parsers.expat.ParserCreate()
f = open(filename, "r")
parser.ParseFile(f)
f.close()
[/sourcecode]

The code above throws an error like this:

[sourcecode lang="shell"]
TypeError: read() did not return a bytes object (type=str)
[/sourcecode]

This source code works in Python 2.6, but failed when running on Python 3.1.

After comparing the manual for the built-in open() function between those 2 versions (2.6 and 3.x versions), I found out that there is a new feature in Python 3.x which is not backward compatibility (unlike transitions between 2.x versions, the transition from 2.x to 3.x may break the backward compatibility).

Python 3.x added the "t" for text, "b" for binary, "+" for updating (read/write) and "U" modifier to the open file mode.

It turns out to be that Python 3.1 no more handles file open as binary by default.Now the text ("t") mode become default for Python 3.1 meanwhile Python 2.6 assume all file access are binary accesses. Python 3.x has implemented modes of more similarity to its C stdio library counterpart than its previous 2.6 version.

Since Python 3.x added additional parameter to the open() function, we must now specify "b" to make it binary access, so that the read() method will return bytes, otherwise it will return str.

[sourcecode lang="python"]
import xml.parsers.expat
import sys
import os.path

xmlFilename = "companies.xml"
p = xml.parsers.expat.ParserCreate()
f = open(xmlFilename, "rb")
p.ParseFile(f)
f.close()
[/sourcecode]

Now the ParseFile() method get what it asks for, a file handler with read() method that return bytes instead of str.

Saturday, July 18, 2009

PyDev 1.4.7 on Eclipse Galileo

WARNING:

The content of this blog is obsolete now, as newer PyDev version 1.5 has been released. Please look at my latest blog post on this.

I begin to have more time to explore the Eclipse Galileo (3.5) again. This time I want to set it up for my Python development, using the PyDev plugin. Current PyDev plugin version is 1.4.7

Assuming you already have a working  installation of Galileo, and have opened a workspace.

The update site for PyDev is http://pydev.sourceforge.net/updates

In Galileo, you need choose: Help > Install New Software...

[caption id="attachment_605" align="aligncenter" width="313" caption="Adding the PyDev Plugin to Eclipse Galileo"]Adding the PyDev Plugin to Eclipse Galileo[/caption]

The "Install" dialog will show up.

eclipse-update-02

Click on the [Add] button at the top right of dialog. You should see this "Add Site" dialog.

eclipse-update-03Type in the data.

Name: Py Dev Update Site
Location: http://www.fabioz.com/pydev/

eclipse-update-04

Click [OK] button.
eclipse-update-05

Tick the checkbox "PyDev for Eclipse" under "PyDev". Click [Next >] button.
eclipse-update-06

Click [Next >].

eclipse-update-07

Click the radio button "I accept the terms of the license agreement" when you agree. Click [Finish] button.

You will see the progress bar.

eclipse-update-08

On completion of the installation process, Eclipse will ask you whether you want to restart.

Answer by clicking the [Yes] button.

Done.

Thursday, July 9, 2009

Python's Lazy Evaluation on Exception Handling

I tried a simple code like this:

[sourcecode lang="python"]
try:
while True:
print('yipee')
except KeyboardInterrupt:
print('w00t')
[/sourcecode]

It runs successfully on command line interface, and keeps printing "yipee" until the user press Ctrl-C. After that I did a typo, which turns out to mistype the "KeyboardInterrupt" as "KeybaordInterrupt".

[sourcecode lang="python"]
try:
while True:
print('yipee')
except KeybaordInterrupt:
print('w00t')
[/sourcecode]

To my surprise, it still runs well, it keeps printing "yipee" to the screen. It's just that
when I press Ctrl-C, Python threw this error:

[sourcecode lang="shell"]
Traceback (most recent call last):
File '<stdin>', line 3, in <module>
KeyboardInterrupt
[/sourcecode]

During handling of the above exception, another exception occurred:

[sourcecode lang="shell"]
Traceback (most recent call last):
File '<stdin>', line 4, in <module>
NameError: name 'KeybaordInterrupt' is not defined
[/sourcecode]

I looked at the documentation of Python 3.1 which says:
The try statement works as follows.

First, the try clause (the statement(s) between the try and except keywords) is executed.

  • If no exception occurs, the except clause is skipped and execution of the try statement is finished.

  • If an exception occurs during execution of the try clause, the rest of the clause is skipped. Then if its type matches the exception named after the except keyword, the except clause is executed, and then execution continues after the try statement.

  • If an exception occurs which does not match the exception named in the except clause, it is passed on to outer try statements; if no handler is found, it is an unhandled exception and execution stops with a message as shown above.


The exception handling in Python works in a lazy manner, they will only validate the except clauses just before processing the exception!

Monday, February 23, 2009

Print command now as a function in Python 3.0

Recently I managed to play around with Python again. The Python 3.0 (now I'm using 3.0.1) treats the print as an ordinary function.

Last time it is a special command:

[sourcecode lang="python"]
print 'hello, world!'
[/sourcecode]

which is treated as a different animal from any other Python functions. Now the Python 3.0 team has return print back to its mainstream:

[sourcecode lang="python"]
print('hello, world')
[/sourcecode]

The behavior of weird comma, a GW-BASIC-like print command also has been fixed here, we have to append a comma to tell Python interpreter not to print a new line character after a print command:

[sourcecode lang="python"]
print "I don't want to skip to",
print "next line"
[/sourcecode]

which will print (it adds space between the words "to" and "next line"):

I don't want to skip to next line

Sometimes, or most of the time, this behavior is considered weird. Of course it is not weird for a used-to-be-a-GW-BASIC/BASICA programmer like me. But for the rest of the world who only knows Pascal, C, Java, C++, etc it is a weird syntax!

Now Python 3.0 comes with the print as a normal Python function:

[sourcecode lang="python"]
print("I don't want to skip to", end="")
print("next line")
[/sourcecode]

which will print:

[sourcecode lang="shell"]
I don't want to skip tonext line
[/sourcecode]

It's good to see that now some of the inconsistencies have been fixed. Of course it took a lot of consideration as they don't want to break the compatibility with previous versions. The 3.0 release is of course an exception. It was released as a breaking version, there will be some backward incompatibility with previous versions (2.x).

Saturday, October 11, 2008

New Release of Python 2.6

A new version of Python, version 2.6 has been released.

This version contains recent addition to the incoming Python 3.0 that doesn't break the current 2.x version's code. As we know, Python 3.0 was designed to break compatibility of 2.x code. Some changes and additions to the 3.0 that is not breaking the 2.x is backported into this 2.6 release.

New modules added to the standard library: multiprocessing, json.

Look at the website: http://www.python.org/download/releases/2.6/

Thursday, September 18, 2008

SCons in Ubuntu Linux box

After fixing the annoying varnish installation problem, I could proceed with installation of SCons in my Ubuntu box.
$ sudo apt-get install scons

Then I created the same SConstruct file, with content:

Program('hello.c')

Invoke SCons:

$ scons




scons: Reading SConscript files ...

scons: done reading SConscript files.

scons: Building targets ...

gcc -o hello.o -c hello.c

gcc -o hello hello.o

scons: done building targets.

Invoke the executable binary:



$ ./hello




hello, world!

It really works as advertised! Excellent!


Wednesday, September 17, 2008

SCons 1.0.1: Python Based Multiplatform Builder Application

I was looking for a way to build application in a Maven  way, but which works beyond Java environment. I know that Maven 2 will somehow able to compile other source code such as C/C++ using some of the plugins. The reason I look for another tools because I might want to maintain my Python code as well.
Google search produced this SCons from Tigris. I downloaded  the version 1.0.1 and try to make a working instance of it.

I downloaded the zip from here, and the installation is straightforward if you already have a Python 2.5.2 installation.

python setup.py install

Voila. It works!

I ran the sample on my Windows machine, create a hello.c code.

int main() {

printf("Hello, world!");

}

Make a SConstruct file containing:

Program('hello.c')

It works as advertised! It invoked the Microsoft Visual C++ Express 8.0 on my machine.

Apart of it, it also produce a byproduct file: .sconsign.dblite of size less than 2k. I guess this is some kind of checksum to check whether the latest build is still up to date.

I will try it again in my VirtualBox Ubuntu machine.