Interfacing with Other Codes
Because Python is an interpreted language— even “compiled” Python is actually interpreted byte code— Python is generally slower than equivalent code in lower-level languages such as C/C++ or Fortran. It may also be the case that a desired piece of functionality already exists in software produced in another computing language and you do not wish to spend the time to re-implement it in Python. In any case it is relatively simple to build interfaces between Python and C and C++, enabling developers to build performance-critical components in a high-performance language. Several of the science and engineering modules, including NumPy and SciPy, use this approach. In the workshop material on Python for High Performance, there is more discussion of the available tools for integrating Python with C/C++ and Fortran. For your own work, it might suffice for you to be able to import one or more of those compiled modules for use within Python, giving you high-level interpreted control coupled with low-level numerical performance. To complement that discussion, we give a brief overview of three different approaches.
At the simplest end of the spectrum — it barely counts as a programming interface at all — Python allows the calling of executables, including options to do it exactly as if summoned from the shell,, with command-line arguments and access to standard input, output and error. The currently recommended method for starting off other processes from Python is to use the subprocess module, which replaces a variety of previous Python tools for this purpose. When using this method of execution, remember that you are effectively starting another program and letting it run; while subprocess
does allow termination of the other process and sending other signals to it, interaction is typically limited to what you would get at the command line if you were typing commands, viewing output and consequently making decisions based on that output. Debugging, therefore, can be disjointed and the behavior of the called executables needs to be reasonably well-understood. As with most Python modules, subprocess
is still evolving, so you should check the documentation specific to your Python version. The subprocess method is particularly applicable if you don’t even have access to the source code for the executable you are running, or it is in a language which you cannot easily interface with Python.
For more direct programmatic functionality, you need to build an interface between Python and the code in question. This is most simply achievable for interfacing with code written in C or C++, although interfaces for some other languages such as Fortran can be achieved. This interface involves producing a Python module from your C/C++ code, which can then be imported and used in Python like any other Python module. The nuts and bolts way to extend Python with code written in C/C++ is to access it through the Python/C API.. Documentation is available at python.org for the Python/C API, and you can find other information on the web. The Python/C API provides a mechanism for converting among objects in Python and data types and functions in C extension modules. This method is particularly suitable if what you need is to add functionality to Python itself.
Wrapping C/C++ is much simpler to execute via software tools, although typically those tools are just facilitating access to the Python/C API under the covers. A wrapper, or shim, is in effect a translation layer between the C and the Python code. There are a variety of tools developed to support the construction of extension modules; some of these tools are discussed in our companion material on Python extensions.