Software Carpentry logo

Integrating Python with C and Fortran

April 24, 2010: We are pleased to announce that Version 4 of this course is now under development. For updates and an early peek at the content, please check out the Software Carpentry blog at http://www.software-carpentry.org/blog/.

1) Introduction

2) You Can Skip This Lecture If...

3) Running External Programs

4) The subprocess Module

5) Running In Place

import subprocess
subprocess.Popen("date")
Mon Apr  3 09:05:39 EST 2006

6) Running With Arguments

import subprocess
subprocess.Popen(["date", "-u"])
Mon Apr  3 13:06:27 EST 2006

7) Capturing Output

import subprocess
SQL = 'select * from Person'
child = subprocess.Popen(['sqlite3', 'experiment.db', SQL],
                         stdout=subprocess.PIPE)
lines = child.stdout.readlines()
for line in lines:
    line = line.strip().split('|')
    print '%s %s (%s)' % (line[1], line[2], line[0])
Kovalevskaya Sofia (skol)
Lomonosov Mikhail (mlom)
Mendeleev Dmitri (dmitri)
Pavlov Ivan (ivan)

8) Providing Input

def pipe_write(filename, lines):
    child = subprocess.Popen(['gzip', '-c'],
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE)
    for line in lines:
        child.stdin.write(line)
    child.stdin.close()
    result = child.stdout.read()
    return result

9) Deadlock

10) Pros and Cons

11) Plan B: Integrating with C

12) How Python Represents Objects

13) Calling Conventions

/* Triple an integer value. */
static PyObject * triple(PyObject * self, PyObject * args)
{
  int val;
  if (!PyArg_ParseTuple(args, "i", &val)) {
    return NULL;
  }
  val = val * 3;
  return Py_BuildValue("i", val);
}

14) Boilerplate

/* Table of module contents (handed back to Python at initialization). */
static PyMethodDef contents[] = {
  {"triple", triple, METH_VARARGS},
  {NULL, NULL}
};

/* Initialization function. */
void inittriple()
{
  Py_InitModule("triple", contents);
}

15) Loading and Calling

import triple
print triple.triple(11)
33

16) What About C++?

17) SWIG

/* triple.i */
 %module triple
 %{
 extern int triple(int n);
 %}

18) Integrating the Other Way

19) Loading Modules

20) Plugin Frameworks

21) Manual Loading

import sys, os

def list_contents(module_name):
    print module_name
    if os.path.dirname(module_name) not in sys.path:
        sys.path.append(os.path.dirname(module_name))
    try:
        module = __import__(module_name)
        for name in vars(module):
            print '\t' + name
    except ImportError:
        print >> sys.stderr, 'Unable to import %s' % module_name

if __name__ == '__main__':
    for module_name in sys.argv[1:]:
        list_contents(module_name)
$ python lister.py lister
lister
        __builtins__
        __name__
        __file__
        list_contents
        __doc__

22) Using Manual Loading

def loader(config_file):
    result = {}
    imported = {}
    infile = open(config_file, 'r')
    for line in config_file:
        name, module, func = line.split()
        if name in result:
            raise LoaderError('Trying to set name %s twice', name)
        if module not in imported:
            imported[module] = __import__(module)
        if func not in imported[module]:
            raise LoaderError('Function %s not in module %s', func, module)
        result[name] = func
    return result

23) Manipulating Namespaces

$ python
Python 2.4.1 (#1, May 27 2005, 18:02:40)
[GCC 3.3.3 (cygwin special)] on cygwin
>>> G = globals()
>>> G
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'G': {...}}
>>> a = 1
>>> G
- {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', 'a': 1, '__doc__': None, 'G': {...}}
>>> del G['a']
>>> G
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'G': {...}}
>>> G['b'] = 2
>>> G
{'b': 2, 'G': {...}, '__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None}
>>> def double(x):
...   return 2 * x
...
>>> G['d'] = double
>>> del G['double']
>>> d
<function double at 0x4d68b4>
>>> G
{'b': 2, 'd': <function double at 0x4d68b4>, 'G': {...}, '__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None}

24) Summary