is an optimizing static compiler for both the Python and the extended Cython programming language (based on Pyrex). It allows you to write C extensions for Python as easy as Python itself. The Cython language is a superset of the Python language that additionally supports calling C functions and declaring C types of variables and class attributes. This allows the compiler to create an efficient C code from Cython code.
Cython yielding performance boosts that can range from a few percent to a large extend, depending on the task at hand. For tasks that are bound by Python’s native object types, the speedups won’t be large enough. But for numerical operations or any operations that are not using Python’s own internal modules, the gains can be massive. The Cython code looks a lot like Python code, by design. If we run the Cython compiler with a Python program (Python 2.x and Python 3.x are both supported), Cython will run it as-is, but none of Cython’s native accelerations will come into play. But if you use the Python code with type annotations in Cython’s special syntax, Cython will be able to replace or substitute fast C equivalents for slow Python objects.
Sample python function to compute the factorial of a number
y = 1
for i in range(1, x+1):
y *= i
Cython version of the corresponding function.
cpdef int test(int x):
cdef int y = 1
cdef int i
for i in range(1, x+1):
y *= i
- Write Python code that works well with C or C++ code natively at any point.
- We can easily convert readable Python code into plain C performance by adding static type declarations, also in Python syntax.
- It uses a combined source code level debugging to find bugs(Python, Cython, and C code).
- Cython lets you interact efficiently with large data sets, e.g. Using multi-dimensional NumPy arrays.
- Provides fast development of applications within the large, mature, and widely used CPython ecosystem.
- We can integrate natively with existing code and data from legacy, low-level, or high-performance libraries and applications.
Build Cython code
There are several tactics to build Cython code:
- Using setuptools setup.py.This is the normal and recommended way.
- Using Pyximport, importing Cython .pyx files as if they were .py files (we need to use setup tools to compile and build in the background). This method is easier than writing a setup.py, but is not that much flexible. So you may need to write a setup.py if, for example, you need certain compilations options.
- Run the Cython command-line utility manually to produce the .c file from the .pyx file, then manually compiling the .c file into a shared object library or DLL suitable for import from Python. (These manual steps are mostly for debugging and experimentation.)
- Use the [Jupyter] notebook or the [Sage] notebook, both of which allow Cython code inline. This is the easiest way to get started writing Cython code and running it.
Building a Cython module using setuptools
Let’s look at a simple “hello world” script in a file hello.pyx:
print(“Hello %s!” % name)
The corresponding setup.py script is provided below:
from setuptools import setup
from Cython.Build import cythonize
name=’Hello world app’,
To build, run python setup.py build_ext –inplace. Then we need to simply start a Python session and do “from hello import say_hello_to” and use the imported function as per our need.
When to use Cython
Now we know how to “Cythonize” a python code, next we need to determine how our Python application or code can benefit from Cython. We must know where to use this.
We can get the best outcomes by using Cython to optimize the following situations in Python functions:
- Functions that run in tight loops, or require long amounts of processing time in a single situation of code.
- The Functions that perform numerical manipulations can be made use of it.
- The Functions that work with objects that can be represented in pure C, such as basic numeric types, arrays, or structures, rather than Python object types like lists, dictionaries, or tuples.
- As we know Python has traditionally been less efficient at loops and numerical manipulations than other, non-interpreted languages. The more you decorate your code to indicate it should use base numerical types that can be turned into C, the faster it will do the number-crunching.
A first step in improving an application’s performance is to profile it—to generate a detailed report to know where the time is being spent during the execution of the program. Python has already provided built-in mechanisms for generating code profiles. And Cython not only hooks into those mechanisms but has profiling tools of its own.
We can get the reports that show, which functions take up the most amount of time in a given Python program from Python’s own profiler, cProfile. By default, Cython code will not be noted in those reports, but you can enable profiling of Cython code by inserting a compiler directive at the top of the .pyx file with the functions you want to include in the profiling:
# cython: profile=True
We can also allow line-by-line tracing of the C code generated by Cython, but this includes a lot of overhead, and so is turned off by default.
Note that profiling can cause a performance hit, so be sure to disable profiling for code that is being shipped into production.