Cython is a python extension that takes a slightly modified Python script file and converts it to C code. That way, it will run about 5-70× as fast on average as the regular python script. Also, python extensions can be written in python.
Pros:
★ Huge speed improvement (can be faster than 70× faster than plain python)
★ Ability to write python extensions with python
★ Added ability to import Cython scripts invisibly with the regular import command
★ Ability to create frozen binaries
★ Ability to combine both C and Python in one binary
★ Very little modification to original python script makes a big difference in speed
★ No editing to source file required
★ By using cython -a and then viewing the outputted html file in a web viewer, you can see which lines of code use python apis (slow), and which ones can be converted to plain c (fast)
Cons:
☆ Must have a working gcc (GNU C Compiler), which is a pain in the @$$ to get working properly on iphoneos
☆ Must have minimal knowledge of C for advanced code optimization
I have built and compiled this already, i just dont have a repo to upload to. Boo? Would you like to host it? Ill build the deb.
Here is the help and usage for the cython shell script:
Cython (http://cython.org) is a compiler for code written in the
Cython language. Cython is based on Pyrex by Greg Ewing.
Usage: cython [options] sourcefile.{pyx,py} ...
Options:
-V, --version Display version number of cython compiler
-l, --create-listing Write error messages to a listing file
-I, --include-dir <directory> Search for include files in named directory
(multiple include directories are allowed).
-o, --output-file <filename> Specify name of generated C file
-t, --timestamps Only compile newer source files
-f, --force Compile all source files (overrides implied -t)
-q, --quiet Don't print module names in recursive mode
-v, --verbose Be verbose, print file names on multiple compilation
-p, --embed-positions If specified, the positions in Cython files of each
function definition is embedded in its docstring.
--cleanup <level> Release interned objects on python exit, for memory debugging.
Level indicates aggressiveness, default 0 releases nothing.
-w, --working <directory> Sets the working directory for Cython (the directory modules
are searched from)
--gdb Output debug information for cygdb
-D, --no-docstrings Strip docstrings from the compiled module.
-a, --annotate Produce a colorized HTML version of the source.
--line-directives Produce #line directives pointing to the .pyx source
--cplus Output a C++ rather than C file.
--embed Generate a main() function that embeds the Python interpreter.
-2 Compile based on Python-2 syntax and code semantics.
-3 Compile based on Python-3 syntax and code semantics.
--fast-fail Abort the compilation on the first error
-X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
Edit: Pros and Cons changed. There are actually no required modifications to the original python script.
Edit: Ways to compile:
1) cython shell script
2)
import pyximport
pyximport.install()
import myCythonScript
PyxInstall allows you to automatically build and compile cython scripts with normal import command.
3) site-packages/sitecustomize.py
↑this file is always run on python start. If you add the following code to it, then the standard import command will always import cython files:
import pyximport
pyximport.install()
pyximport.install() takes an optional argument, which specifies whether or not normal python files should be attempted to be compiled with cython during import or not.
4) distutils setup.py
This is probably the most cumbersome method of compiling, because you must write a new python script for each cython file. There is plenty of documentation about this online, so ill let you google it if you want to use this method of compiling.
I usually use either option 1) or 3).
The Cython script files are .pyx files. Here is a comparison of a Python script and a Cython script. Both files find prime numbers.
Normal python code:
def primes(kmax):
p = []
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] != 0:
i = i + 1
if i == k:
p.append(n)
k = k + 1
n = n + 1
return p
Faster cython code:
def primes(int kmax):
# cdef int n, k, i
cdef int p[1000]
result = []
if kmax > 1000:
kmax = 1000
k = 0
n = 2
while k < kmax:
i = 0
while i < k and n % p[i] <> 0:
i = i + 1
if i == k:
p[k] = n
k = k + 1
result.append(n)
n = n + 1
return result
Notice the similarity?
Look at this:
Filename: cmath.pyx
cdef extern from "math.h":
double c_lgamma "lgamma" (double)
double c_exp "exp" (double)
def exp(n):
"""Return e**n."""
return c_exp(n)
def lfactorial(n):
"""Return an estimate of the log factorial of n."""
return c_lgamma(n+1)
def factorial(n):
"""Return an estimate of the factorial of n."""
return c_exp( c_lgamma(n+1) )
if __name__ == "__main__":
import sys
if len(sys.argv) != 2:
sys.stderr.write("USAGE: %s n\nPrints n!.\n" % sys.argv[0])
sys.exit(2)
n, = map(float, sys.argv[1:])
print factorial(n)
And:
Filename: combinatorics.pyx
import cmath
def nCr(n, r):
"""Return the number of ways to choose r elements of a set of n."""
return cmath.exp( cmath.lfactorial(n) - cmath.lfactorial(r)
- cmath.lfactorial(n-r) )
if __name__ == "__main__":
import sys
if len(sys.argv) != 3:
sys.stderr.write("USAGE: %s n r\nPrints n-choose-r.\n" % sys.argv[0])
sys.exit(2)
n, r = map(float, sys.argv[1:])
print nCr(n, r)
The cdef extern from "math.h" part loads a c function from a header. Cython can run c code.
In cython, code files end with the .pyx extension. It is python with c data types. Here i have a cython script, very simple.
cdef char* sayHi():
return "Hello, world!"
print(sayHi())
This is the same as python except for the first line.
cdef means that you are defining an object with a c data type. For example,
cdef int count = 5.
cdef does not necessarily mean to define a function, but could define functions, classes, and variables.
char* sayHi(): means that a function called
sayHi will be created and will return a
char* value. A
char* is like a c version of a string. Notice the
return "Hello, world!". it returns a python string, which Cython automatically converts to a
char*, or a c string. Then, now that
sayHi() is defined, we do
print(sayHi()). What this means is that we will print to stdout, or the terminal screen, whatever value that the function
sayHi() returns. Since we made
sayHi() always return the string "Hello, world!", then
print will output the following: Hello, world!
Heres a screenshot of how this works:

I am able to run hello.pyx via the import command because i ran this beforehand:
import pyximport; pyximport.install().
You didnt see me run it, because i put this line of code in /usr/lib/python2.5/site-packages/sitecustomize.py. This file, sitecustomize.py, is always executed when the python interpreter starts.
pyximport.install() adds functionality to the
import command to automatically compile cython files and run them as if they were normal python code. When i package Cython, i will make two packages: Cython, and pyximport. When you install pyximport, it will automatically add this line of code to sitecustomize.py. Release coming soon.