Tuesday, August 26, 2008

Speeding up Python code with Psyco

Possibly the easiest way of speeding up Python code is to use Psyco. Psyco is extremely easy to use and it is at least worth a try before delving into C/C++ mess either directly or with the help of scipy.weave.
The usage is simple, just download Psyco, install it and add following to your code:
import psyco
psyco.full()
The full() directive tells Psyco to optimize everything. I usually put these two lines to the beginning of the code, just after other imports. Psyco website states that possible speedups can be between 2x-100x. I have seen every number between 10% faster to 50x faster code execution.
The following is an example of very high acceleration of very simple code:
def test(N, M):
res = []
for i in range(N):
for j in range(M):
if j == 0:
x = i*i*i
res.append(x)
return res
Running this function with N = 10000 and M = 100000 takes ~60 seconds on Intel E8200 processor. After importing and running Psyco the very same code takes ~1.2 seconds. The speedup is then ~50x.
Psyco works best on functions which run at least couple of seconds per each call and are similar to the presented test function. Psyco only optimizes code within functions and scripts classes but this isn't really a problem.
To only optimize one function use
psyco.bind(yourfunctionname)

Saturday, August 23, 2008

Improving blogger template style - Sand Dollar

There is something what I don't like on my currently selected blogger template style - the Sand Dollar. It spans all available screen real estate from left to right. I would like to make it fixed-width and centered. To achieve this, I've changed the '#outer-wrapper' part of the template by adding 'width: 980px;'. This makes the rendered web page stay only 980 pixels wide which should be enough even on 1024 pixel wide common displays.
To center web page contents, just add 'margin: 0 auto;' to the same section. This means in english: top and bottom margins are zero, left and right margins are set by browser (which means content will be centered). You can find the specifications of the margin command here.

The entire outer-wrapper section now looks like this:

#outer-wrapper {
font:$bodyfont;
width: 980px;
margin: 0 auto;
}

Thursday, August 21, 2008

scipy.weave doesn't work - compiler troubles

The scientific python package SciPy contains a very powerful library called weave. Weave enables one to relatively easily embed C/C++ code into Python code. Thus, if you happen to have a computationally intensive code you can gain a lot of speed by rewriting it in C/C++. There are a lot of ways of how to accomplish this but weave makes this feat relatively easy even for an amateur like me.
There is however one caveate for Windows users. I commonly install all software into the 'C:\Program files\' directory. If you do this with Python and a weave requirement, MinGW compiler, weave will not work. The trouble is the space within directory name. Weave scripts and possibly also gcc are not written to deal with spaces within paths and will not find required files like gcc.exe. You will end up with error messages like:
error: command 'gcc' failed: No such file or directory
ValueError: The 'mingw32' compiler was not found.
At first I have made a hack in the first affected script, the 'platform_info.py', but this only resulted in another error:
Could not locate executable g++
Executable g++ does not exist
Traceback (most recent call last):
File "G:\Temp\tmpfgm8bn\_ev-uq.py", line 8, in
s,o = exec_command(cmd, _with_python=0, **{})
File "C:\Program Files\Python25\lib\site-packages\numpy\distutils\exec_command.py", line 253, in exec_command
use_tee=use_tee,**env)
File "C:\Program Files\Python25\lib\site-packages\numpy\distutils\exec_command.py", line 402, in _exec_command
so_dup = os.dup(so_fileno)
OSError: [Errno 9] Bad file descriptor
So, to make things short, just install Python and MinGW into C:\. This will save you from a lot of trouble.
UPDATE 08/10/22: It turned out today that your user name also may not have a space within it. I've just spent an hour trying to get weave working on a colleague's computer where the username is actually a "user name". No, renaming the user does not do the trick. I 'solved' it by creating a new user with 'valid' username.

Tuesday, August 19, 2008

Strange scipy.weave import error

Today, I've booted my PC and tried to run a script which uses scipy.weave package. What I got was a rather unusual error:
EOFError: EOF read where object expected

I've tried to type
import scipy.weave
which just reproduced the error. After some thinking I got an idea that some files were broken. A scipy reinstall however warned that some files are broken and cannot be (re)written. So I run the scandisk/chkdsk/whatever its name currently is. It did find some errors within files mentioned in the error message. Nonetheless the import still didn't work, this time replying with another error:
ValueError: bad marshal data

After this I tried repairing both scipy and Python installations to no success. No warnings this time though.
Finally, I uninstalled Python alltogether and deleted all files and directories within C:\Python25\. After installing everything back everything seems to fine allright. I think it is the first such error since I've started using NTFS as my filesystem some five or six years ago.

Monday, August 18, 2008

Text box with scrollbar

A very nice example can be found here.
I you want to move focus so that the last entry in the text box will be visible, you may modify the code as follows:


import Tkinter

root = Tkinter.Tk()
s = Tkinter.Scrollbar(root)
T = Tkinter.Text(root)

T.focus_set()
s.pack(side=Tkinter.RIGHT, fill=Tkinter.Y)
T.pack(side=Tkinter.LEFT, fill=Tkinter.Y)
s.config(command=T.yview)
T.config(yscrollcommand=s.set)

for i in range(40):
T.insert(Tkinter.END, "This is line %d\n" % i)
T.yview(Tkinter.MOVETO, 1.0)

Tkinter.mainloop()

The 1.0 parameter of .yview means the end of the Text widget contents.
I'm usually using the Grid geometry manager and aligning the scrollbar with it requires some more work than with pack. Nothing out of ordinary though.

Friday, August 8, 2008

Filenames, paths, .zip files and such in Python

It may be hard to believe but I've had troubles looking for a way how to split a path to a file into filename and the path to it. So here it is. Let's have a path such as this:
'C:/Python25/python.exe'
we want to separate a file name 'python.exe' from the path to it 'C:/Python25/'. With the help of a standard Python module os.path it is an easy task to do:

import os.path
mypath = 'C:/Python25/python.exe'
separated = os.path.split(mypath)

where 'separated' is a tuple with two items. First is the path, second is the filename.
Do you also want to separate file name from its extension (e.g. '.exe' in our case)? It's easy:


name,extension = os.path.splitext(separated[1])

Do you also want to reverse this process? Just call the os.path.join() function:

completefilename = os.path.join(separated[0],separated[1])

Finally, I also wanted to compress some files to save disk space. There is a standard Python library called zipfile which supports creating .zip files (it also requires another library called zlib for compression of the .zip archives). Usage is simple:

import zipfile
f = zipfile.ZipFile( 'myfile.zip', 'w', compression = zipfile.ZIP_DEFLATED)
f.write('mydata.txt')
f.close()

The 'ZIP_DEFLATED' option tells the ZipFile class to compress the data, otherwise no compression is done.

Monday, July 28, 2008

Windows XP Home won't allow login after installation, domain error

I've recently installed Windows XP Home to a computer which was previously equipped with Win XP Professional. There was a minor glitch during the installation when the installer refused to delete the C: partition because there were some installation files present. This was possibly caused by inserting the install CD into running computer, the installer then copied some files into C: and expected to put Windows on a D: or E: partition. After reset a new installation started and run OK. Unfortunately, I couldn't log in into the machine although I haven't set any password for the only user account set up during installation. The message was "Domain does not Exist" with "smart" advice to contact system administrator. I've found several questions posted on the web regarding the same problem but no real answer to the problem. The trouble is, I have not set up any domain and Win XP Home officially does not even support domains!
My conclusion was that the installer somehow picked up some remnants of the previous Win XP Pro system (which does support domains but on this PC was not using them) and malfunctioned.

So I've done a reinstall with following steps:
1) format not only C: but also D: partitions;
2) full format on C: to NTFS before system installation begins (i.e. not the fast formatting option); it takes about 12 minutes on a 50 GB partition;
3) different user name from the previous (XP Pro) system.

I'm not sure whether these steps are all necessary or which one did the trick but after second installation everything works as it should.