Sunday, October 28, 2012

pythonxy cython mingw problems

Again I was having issues using a cython compiled package with pythonxy. For some reason when running from a ipython terminal started from pythonxy, I would get a DLL load error. If I would run the python/cython program directly (i.e. from a dos box: python my_program.py) then it would run fine. By default if you compile a program with mingw you need a dll with the std c or c++ library (typically this dll has a difficult name as libgcc_s_dw2-1.dll). As I have mingw installed in more than one location (32bit, 64bit, QtSDK, Python(x,y)) I think it cannot find the right dll (although I could not detect which dll it was using). The problem can be most easily solved if you link the std library statically. This you can do by simply adding "stdc++" to your libraries field in setup.py.

So my new setup.py looks now something like

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy

ext_modules = [Extension("BvL_cython",["model_cython.pyx"],\
    libraries=["m","stdc++"],include_dirs=[numpy.get_include()])]

setup(
    name= 'Model class',
    cmdclass = {'build_ext': build_ext},
    ext_modules = ext_modules
)

(This also shows how to automatically detect the location of the numpy include directories)

Saturday, October 13, 2012

Color text output from python

At the moment I run a minimization routine build in Cython/Python that outputs a lot of text to the terminal. Not all text is equally interesting and I was wondering if it is difficult to output some of the more important messages in a different color. It turns out that this is very easy. On stackoverflow Dietrich Epp posted a nice example which I have changed a little to select the color with a single character string:

def hilite(string, status, bold):
    attr = []
    if(sys.stdout.isatty()):
        if status=='g':
            # green
            attr.append('32')
        elif status=='r':
            # red
            attr.append('31')
        elif status=='y':
            # yellow
            attr.append('33')    
        elif status=='b':
            # blue
            attr.append('34')
        elif status=='m':
            # magenta
            attr.append('35')
        if bold:
            attr.append('1')

        return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), string)
    else:
        return(string)

More info on ANSI escape codes is given on Wikipedia. You can also do things like underline. So far I have only tested this on Linux so I do not know if it also works on Windows.

Update:
This does not work on Windows (windows terminals do not work with ANSI codes). Luckily there is a python package you can use to make it work on windows after all: colorama. Simply call colorama.init()
(after import colorama) and you can use the above code again. However, I noticed that if you use ipython this garbles your prompt (and other things). To work around this I call colorama.init() in the functions that use the ANSI codes in the output. Then when the script is finished you have to call colorama.deinit() and ipython will behave normally.