The Python C-API
Wed 03 April 2019 by Michael OlbergExtending the Python Interpreter with C/C++
The Python interpreter can be extended via C (or C++) code to
- make existing python code execute faster by replacing critical sections into compiled code
- interface to existing/legacy C (or C++) libraries
- make C structures (C++ classes) first class objects within python
In my work I was guided by the following documentation (Python 3.0): extending and embedding the Python interpreter
In my demonstration I'll be using an interface I wrote to the CLASSIC data format (used by CLASS/GILDAS), please ask me for the source code if you are interested.
To start with I wrote some C++ classes which implement a reader class
for the two types of CLASSIC files, V1 or V2. My C++ code allows to
open a file, determine the file type and return a reader which will
allow to retrieve the header, data vector or frequency vector for a
given id, which ranges from 1 to the number returned by the
getDirectory
method. Example below is for the V2 reader class:
/**
* A class to read a CLASSIC file of type 2.
*
*/
class Type2Reader : public ClassReader {
public:
Type2Reader(const char *);
~Type2Reader();
int getDirectory();
SpectrumHeader getHead(int scan);
std::vector<double> getFreq(int scan);
std::vector<double> getData(int scan);
private:
void getFileDescriptor();
void getEntry(int k);
FileDescriptor2 fdesc;
Type2Entry centry;
ClassSection2 csect;
long int ext[MAXEXT];
};
In my Python code I wanted to be able to use code like the following:
import sys
import pandas as pd
import numpy as np
import classic # my python module!
print(classic.version())
if len(sys.argv) == 1:
print("usage: %s <filename>" % (sys.argv[0]))
sys.exit(1)
classfile = sys.argv[1]
foo = classic.Reader(classfile)
# get number of spectra in file
nscans = foo.getDirectory()
print("number of spectra = %d (%d)" % (nscans, foo.count))
headers = []
for i in range(nscans):
headers.append(foo.getHead(i+1))
df = pd.DataFrame(headers)
iscan = 1
if len(sys.argv) > 2:
iscan = int(sys.argv[2])
freq = foo.getFreq(iscan)
data = foo.getData(iscan)
nchan = len(freq)
for i in range(nchan):
print("%10.5f %10.5f" % (freq[i], data[i]))
All code is available at this git repository.
Some features of numpy arrays
- check out the numpy website for docs and the like
- feel free to download and play around with the jupyter notebook on numpy
Installation
- assuming you have 'pip' installed run the following
pip install numpy
pandas
pandas: powerful Python data analysis toolkit
Useful links:
A tip: Whenever you are using pandas
in your own code, try and stick to the following convention:
import pandas as pd
This will make it easier for other people to understand your …
read moreastropy - the python astronomy package
- get it from here
- there are a number of great examples to get you started (the examples I showed in the seminar came from here)
- and further tutorials
- also check out the astropy-page on the WCS
What it can be used for (biased, certainly not complete list)
- reading+writing standard …
Coding in python in a Jupyter Notebook
- I made some slides showing how to get started
- check out the jupyter website for docs and the like
- for further info on the jupyter extensions check out their github page
- feel free to download and play around with the notebook we worked on; (tarball contains both the notebook and …
Anaconda
The Anaconda distribution for Python
-
The slides are in this anaconda.pdf
-
Anaconda is a distribution for python which
- comes with pre-built and pre-configured collection of packages
- package manager (
conda
) - version management
- ... and more
-
Freemium software from Continuum Analytics
- Works basically the same on Win, Mac and Linux
- Self-contained, install …