FAQ¶
Note
This page has been migrated from the wiki on github and is in the process ofbeing updated; please open an issue or a PR if you find something to improve.
Basics¶
Do I need to rename my.py
file to.pyx
?¶
Answer: No. Cython can compile both .py and .pyx files. The difference is that the extended Cython syntax (cdef…
) is only available in Cython .pyx files and not in Python .py files.
But you can use Cython’spure Python mode to provide type declarations for the compilation, including Python’s PEP-484 syntax for type hints.
For cases where no interaction with external C libraries is required, this is also the recommended way to type your code, since sticking to .py files with regular Python syntax keeps the whole range of debugging, linting, formatting, profiling etc. tools for Python code available for your software development needs, which usually cannot handle the syntax of .pyx files.
Can Cython generate C code for classes?¶
Answer: A plain class becomes a fully-fledged Python class.Cython can also generate C classes, where the class data is stored in anefficient C structure at the cost of some additional limitations.
Can I call my Python code from C?¶
Answer: Yes, easily. Follow the example inDemos/callback/ in the Cython source distribution.
How do I interface numpy arrays using Cython?¶
Answer: Follow theexample.
How do I compile Cython with subpackages?¶
Answer: It’s highly recommended to arrange Cython modules in exactly thesame Python package structure as the Python parts of the code base. As long asyou don’t keep your Cython code in unusual places, everything should just work.
This is in part due to the fact that fully qualified names are resolved atcompile time, and moving.so
files around or adding__init__
filesbetween the Cython compile and the Python runtime invocation means thatcimports and imports may resolve differently. Failure to do this may result inerrors like .pxd files not found or'module'objecthasnoattribute'__pyx_capi__'
.
How do I speed up the C compilation?¶
Answer: Especially with large modules, the code that Cython generates cantake the C compiler quite some time to optimise. This is usually ok forproduction builds, but during development, this can get in the way.
It can substantially speed up the C compiler runs to disable the codeoptimisation, e.g. by setting the environment variableCFLAGS="-O0-ggdb"
on Linux or MacOS, which also enables full debugging symbols for better crashreports and debugger usage. For MSVC on Windows, you can pass the option/Od
to disable all optimisations.
How do I reduce the size of the binary modules?¶
Answer: The Python distutils build often includes debugging symbols in theextension modules. The default for gcc is-g2
, for example. Disabling them(CFLAGS=-g0
for gcc), or setting them to the bare minimum that is requiredto produce stack traces on crashes (CFLAGS=-g1
for gcc), can visibly reducethe size of the binaries.
Here are some more things to try:
If you don’t need pickle support for your cdef classes, memoryviews or functions,consider disabling auto-pickle support with a directive:
# cython: auto_pickle=False# you can still enable or disable it locally for single class:@cython.auto_pickle(True)@cclassclassMyClass:...
If you do not need C line information in exception stack traces (i.e. Python/Cythonlines are enough, as for normal Python code), you can disable this feature with theC macro
CYTHON_CLINE_IN_TRACEBACK
:-DCYTHON_CLINE_IN_TRACEBACK=0
In Cython versions before 3.1, you also had to pass the option
--no-c-in-traceback
or set the optionc_line_in_traceback=False
to get the reduction in size.If you do not need Cython implemented functions to look and behave like Pythonfunctions when it comes to introspection (argument names, annotations, etc.),you can turn off the
binding
directive, either globally, or locally for classesor specific functions. This will make Cython use the normal CPython implementationfor natively implemented functions, which does not expose such functionality.If you do not need to expose the docstrings of Python functions and classes,you can exclude them from the extension module with the option
Cython.Compiler.Options.docstrings
.If you use memoryviews in multiple modules, you can generate and use a shared utility module.This approach will allow you to have one single utility code shared between all cython modulesinstead of having them replicated in every module. SeeShared utility module for more detail.
How well is Unicode supported?¶
Answer: The support for Unicode is as good as CPython’s, but additionallydistinguishes between the Pythonstr
(bytes
in Python 2.7) andunicode
(always Unicode text) string type. Note that there is no equivalentC type available for Unicode strings, but Cython can automatically convert(encode/decode) from and to encoded C/C++ strings (char*
/std::string
).
See thestring tutorial.
How do I …?¶
How do I pickle cdef classes?¶
Answer: Seethe documentation.
How do I help Cython find numpy header files?¶
Answer: If you are seeing errors like these:
error:numpy/arrayobject.h:Nosuchfileordirectoryerror:numpy/ufuncobject.h:Nosuchfileordirectory
You should modify your setup.py file to grab the numpy include directory as follows:
importnumpy...setup(...ext_modules=[Extension(...,include_dirs=[numpy.get_include()])])
How do I declare numeric or integer C types?¶
Answer: In most cases, you don’t need to. For types declared instdint.h
, justcimport
them fromlibc.stdint
which comes withCython, e.g.
fromlibc.stdintcimportuint32_t,int64_tcdefint64_ti=5
For non-standard types, it’s enough to provide Cython with actypedef
declaration that maps them to a closely related standard C type, e.g.
cdefexternfrom"someheader.h":ctypedefunsignedlongMySpecialCInt_tcdefMySpecialCInt_ti
Make sure you then use the original C (typedef) type name in your code, not thereplacement type that you chose for the declaration in Cython!
The exact size of the type at C compile time is not that important becauseCython generates automatic size detection code (evaluated at C compile time).However, when your code mixes different types in arithmetic code, Cython mustknow about the correct signedness and the approximate longness in order toinfer the appropriate result type of an expression. Therefore, when using actypedef
as above, try to come up with a good approximation of the expectedC type. Since the largest type wins in mixed arithmetic expressions, it’susually not a problem if the type turns out to be somewhat larger than what theC compiler eventually determines for a given platform. In the worst case, ifyour replacement type is substantially larger than the real C type (say, ‘longlong’ instead of ‘int’), you may end up with slightly slower conversion code.However, if the type is declared too small and Cython considers it smaller thanother types it is used together with, Cython may infer the wrong type for anexpression and may end up generating incorrect coercion code. You may or maynot get a warning by the C compiler in this case.
Also note that Cython will consider large integer literals (>32 bit signed)unsafe to use in C code and may therefore use Python objects to represent them.You can make sure a large literal is considered a safe C literal by appending aC suffix, such as ‘LL’ or ‘UL’. Note that a single ‘L’ is not considered a Csuffix in Python 2 code.
How do I declare an object of type bool?¶
Answer: Well, that depends on whether you want the C99/C++bool
or thePythonbool
. Previously, Cython always defaulted to the Pythonbool
type, which led to hard-to-debug issues when users unsuspectingly usedbool
in wrapping C++ code. We decided to make the choice explicit – you can importwhichever you’d like:
For the Python type, do
fromcpythoncimportbool
.For the C++ type, do
fromlibcppcimportbool
.
Note that there is also a type calledbint
, which is essentially a Cint
but automatically coerces from and to a Python bool value, i.e.cdefobjectx=<bint>some_c_integer_value
gives eitherTrue
orFalse
.
How do I useconst
?¶
Answer: You can just use it in your code and in your declarations.
How do I use builtins likelen()
with the C typechar*
?¶
Answer: Cython mapslen(char*)
directly tostrlen()
, which meansthat it will count the number of characters up to the first 0 byte. Similarly,(char*).decode(...)
is optimised into a C-API call, and applying it toslicedchar*
values will skip the length counting step.
See thestring tutorial.
For other Python operations onchar*
, the generated code may beinefficient, as a temporary object may have to get created. If you notice thisfor your code and think that Cython can do better, please speak up on themailing list.
How do I make a cdef’d class that derives from a builtin Python type such as list?¶
Answer: You can just use the type as a base class in your cdef class declaration.
The only exception are the types bytes (‘str’ in Python 2) and tuple, which canonly be subtyped by Python classes (not cdef classes). This is considered abug. However, you cansafely subtype ‘unicode’ and ‘list’ instead.
How do I raise an exception in Cython code that will be visible to ancestor (in the callstack) CPython code?¶
Answer:
If your cdef or cpdef function or method does not declare a return type (as isnormal in CPython code), then you get exceptions without any extra effort.
If your cdef or cpdef function or method declares a C-style return type, seeError return values.
How do I declare a global variable?¶
Answer:
globalvariable
How do I assign to a global variable?¶
Answer: You need to declare the variable to be global (see above) beforetrying to assign to it. Often this occurs when one has code like
cdefint *datadeffoo(n):data=malloc(n*sizeof(int))
This will result in an error “Cannot convert'int*'
to Python object.”This is because, as in Python, assignment declares a local variable. Instead,you must write
cdefint *datadeffoo(n):globaldatadata=malloc(n*sizeof(int))
Seehttp://docs.python.org/tutorial/classes.html#python-scopes-and-namespacesfor more details.
How do I create objects or apply operators to locally created objects as pure C code?¶
Answer: For methods like__init__
and__getitem__
the Pythoncalling convention is mandatory and identical for all objects, so Cython cannotprovide a major speed-up for them.
To instantiate an extension type, however, the fastest way is to actually usethe normal Python idiom of calling the__new__()
method of a type:
cdefclassExampleClass:cdefint_valuedef__init__(self):# calling "__new__()" will not call "__init__()" !raiseTypeError("This class cannot be instantiated from Python")cdefExampleClass_factory():cdefExampleClassinstance=ExampleClass.__new__(ExampleClass)instance._value=1returninstance
Note that this has similar restrictions as the normal Python code: it will notcall the__init__()
method (which makes it quite a bit faster). Also, whileall Python class members will be initialised to None, you have to take care toinitialise the C members. Either the__cinit__()
method or a factoryfunction like the one above are good places to do so.
How do I implement a single class method in a Cython module?¶
Answer: As of Cython 3.0, Cython-defined methods bind by default.That means that the following should work:
#!pythonimportcython_moduleclassA(object):method=cython_module.optimized_method
How do I pass string buffers that may contain 0 bytes to Cython?¶
Answer: See thestring tutorial.
You need to use either a Python byte string object or a char*/length pair ofvariables.
The normal way to convert a char* to a Python byte string is as follows:
#!pythoncdefchar*s="a normal C byte string"cdefbytesa_python_byte_string=s
However, this will not work for C strings that contain 0 bytes, as a 0 byte isthe normal C way of terminating a string. So the above method will cut thestring at the first 0 byte. To handle this case correctly, you have to specifythe total length of the string that you want to convert:
cdefchar*s="an unusual\0 containing C byte string"a_python_byte_string=s[:21]# take the first 21 bytes of the string, including the \0 byte
Note that this will not handle the case that the specified slice length islonger than the actual C string. This code will crash if the allocated memoryarea of thechar*
is shorter.
There is also support for decoding a C string slice efficiently into a Pythonunicode string like this:
# -*- coding: ISO8859-15cdefchar*s="a UTF-8 encoded C string with fünny chäräctörs"cdefPy_ssize_tbyte_length=46a_python_unicode_string=s[:byte_length].decode('ISO8859-15')
How do I pass a Python string parameter on to a C library?¶
See thestring tutorial <string_tutorial>.
Answer: It depends on the semantics of the string. Imagine you have this C function:
cdefexternfrom"something.h":cdefintc_handle_data(char*data,intlength)
Forbinary data, you can simply require byte strings at the API level, sothat this will work:
defwork_with_binary_data(bytesbinary_data):c_handle_data(binary_data,len(binary_data))
It will raise an error (with a message that may or may not be appropriate foryour use case) if users pass other things than a byte string.
Fortextual data, however, you must handle Unicode data input. What you dowith it depends on what your C function accepts. For example, if it requiresUTF-8 encoded byte sequences, this might work:
defwork_with_text_data(text):ifnotisinstance(text,unicode):raiseValueError("requires text input, got%s"%type(text))utf8_data=text.encode('UTF-8')c_handle_data(utf8_data,len(utf8_data))
Note that this also accepts subtypes of the Python unicode type. Typing the“text” parameter as “unicode” will not cover this case.
How do I use variable args?¶
Answer: For a regular function, just use*args
as in Python.
For a C-function it can’t be done cleanly yet, but you can use the Cva_args
mechanism:
cdefexternfrom"stdarg.h":ctypedefstructva_list:passctypedefstructfake_type:passvoidva_start(va_list,void*arg)void*va_arg(va_list,fake_type)voidva_end(va_list)fake_typeint_type"int"cdefintfoo(intn,...):print"starting"cdefva_listargsva_start(args,<void*>n)whilen!=0:printnn=<int>va_arg(args,int_type)va_end(args)print"done"defcall_foo():foo(1,2,3,0)foo(1,2,0)
How do I make a standalone binary from a Python program using cython?¶
Answer: You probably want a recipe something like this:
The magic is the--embed
option, which embeds a copy of the Python interpretermain in the generated C. You’ll want to change'foobar'
to reflect the name ofyour script, of course, andPYVERSION
as appropriate.
More details can be foundin the embedding documentation.
How do I have to wrap C code that uses the restrict qualifier?¶
Answer: There currently is no way of doing this directly into C code. Cython does not understand the restrict qualifier. However you can wrap your way around it.
See the following example code:
slurp.h¶
#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <regex.h>#include <Python.h>intth_match(char*,char*);
cslurp.c¶
#include "slurp.h"intth_match(char*string,char*pattern){intstatus;regex_tre;if(regcomp(&re,pattern,REG_EXTENDED|REG_NOSUB)!=0){return0;}status=regexec(&re,string,(size_t)0,NULL,0);regfree(&re);if(status!=0)return0;return1;}
slurp.pyx¶
cdefexternfrom"slurp.h":intth_match(char*st,char*pt)classSlurp:''' This is a simple, but optimized PEG (Parser Expression Group) parser. It will parse through anything you hand it provided what you hand it has a readline() method. Example: import sys from thci.ext import slurp o = slurp.Slurp() o.register_trigger('^root:.*:.*:.*:.*$', sys.stdout.write) o.process(open('/etc/passwd', 'r')) '''def__init__(self):''' __init__(self) '''self.map={}self.idx=0defregister_trigger(self,patt=None,cback=None,args=None):''' register_trigger(self, patt=None, cback=None, args=None) '''ifpatt==Noneorcback==None:returnFalseifargs==None:args=Falseself.map[self.idx]=(patt,cback,args)self.idx+=0returnTruedefprocess(self,fp=None):''' process(self, fp=None) '''iffp==None:returnFalsewhileTrue:buf=fp.readline()ifnotbuf:breakforpatt,cback,argsinself.map.values():ifth_match(buf,patt)==True:ifargs==False:cback(buf.strip())else:cback(buf.strip(),args)
This avoids the problems using the restrict qualifiers (Such as are needed withthe functions declared in regex.h on FreeBSD [at least 7.X]) by allowing the Ccompiler to handle things going from C to C, Cython’s support for this evenusing the “const trick” doesn’t seem to behave properly (at least as of 0.12).the following commands will generate your compiled module from the abovesource:
cython-oslurp.cslurp.pyxcc-shared-I/usr/include-I./-I/usr/local/include/python2.5-L/usr/local/lib-lpthread-lpython2.5cslurp.cslurp.c-oslurp.so
It is also possible to use distutils by adding the file cslurp.c (or your filesname) to the list of files to be compiled for the extension.
How do I automatically generate Cython definition files from C (.h) or C++ (.hpp) header files ?¶
Answer: Several people have created scripts to parse header files andautomatically produce Cython bindings.
autowrap
autowrap automatically generates python extension modules for wrapping C++libraries based on annotated (commented) cython pxd files. Current featuresinclude wrapping of template classes, enums, free functions and static methodsas well as converters from Python data types to (many) STL containers and back.Finally, also manually written Cython code can be incorporated for wrappingcode.
http://github.com/uweschmitt/autowrap
python-autopxd
Automatically generate pxd from C headers. It uses[pycparser](https://github.com/eliben/pycparser) to parse the definitions, sothe only requirement beyond python dependencies is a C preprocessor on PATH.
https://github.com/gabrieldemarmiesse/python-autopxd2 (A friendly fork ofpython-autopxd, supporting recent Python versions)
https://github.com/tarruda/python-autopxd (original version)
How do I run doctests in Cython code (pyx files)?¶
Answer:
Cython generates a__test__
dictionary in the module that contains alldocstrings of Python visible functions and classes that look like doctests(i.e. that contain>>>
). The doctest module will properly pick this up andrun the doctests.
This module (let’s call it “cydoctest”) offers a Cython-compatible workaround.
#!python"""Cython-compatible wrapper for doctest.testmod().Usage example, assuming a Cython module mymod.pyx is compiled.This is run from the command line, passing a command to Python:python -c "import cydoctest, mymod; cydoctest.testmod(mymod)"(This still won't let a Cython module run its own doctestswhen called with "python mymod.py", but it's pretty close.Further options can be passed to testmod() as desired, e.g.verbose=True.)"""importdoctestimportinspectdef_from_module(module,object):""" Return true if the given object is defined in the given module. """ifmoduleisNone:returnTrueelifinspect.getmodule(object)isnotNone:returnmoduleisinspect.getmodule(object)elifinspect.isfunction(object):returnmodule.__dict__isobject.func_globalselifinspect.isclass(object):returnmodule.__name__==object.__module__elifhasattr(object,'__module__'):returnmodule.__name__==object.__module__elifisinstance(object,property):returnTrue# [XX] no way not be sure.else:raiseValueError("object must be a class or function")deffix_module_doctest(module):""" Extract docstrings from cython functions, that would be skipped by doctest otherwise. """module.__test__={}fornameindir(module):value=getattr(module,name)ifinspect.isbuiltin(value)andisinstance(value.__doc__,str)and_from_module(module,value):module.__test__[name]=value.__doc__deftestmod(m=None,*args,**kwargs):""" Fix a Cython module's doctests, then call doctest.testmod() All other arguments are passed directly to doctest.testmod(). """fix_module_doctest(m)doctest.testmod(m,*args,**kwargs)
How do I work around the-Wno-long-doubleerror
when installing on OS X?¶
Answer:
This is a known issue in OS X with some Python installs. It has nothing to dowith Cython, and you will run on the same troubleevery time you want tobuild an C extension module.
This is the most sane (if not the only) way to fix it:
Enter Python prompt, and type this:
>>>fromdistutilsimportsysconfig>>>sysconfig.get_makefile_filename()
That should output the full path of a ‘Makefile’… Open that filewith any text editor and remove all occurrences of ‘-Wno-long-double’flag.
How do I work around the “unable to find vcvarsall.bat” error when using MinGW as the compiler (on Windows)?¶
Answer: This error means that Python cannot find the C++ compiler on yoursystem. Normally, this is managed by distutils, but it may happen that it’s notyet up-to-date. For example, you may be using this in setup.py:
fromdistutils.coreimportsetupfromdistutils.extensionimportExtension
Instead, you can try to load setuptools, which will monkey-patch distutils tofind vcvarsall.bat:
try:fromsetuptoolsimportsetupfromsetuptoolsimportExtensionexceptImportError:fromdistutils.coreimportsetupfromdistutils.extensionimportExtension
In IPython, you can just import setuptools, like this:
# First cell:importsetuptools%load_extCython# Second cell:%%cython-aimportcythoncimportcythoncdefintalpha=255printalpha
If this is unsuccessful, try the following workarounds.
If no python libraries are imported, define the compiler by adding thefollowing statement:
--compiler=mingw32
Therefore, the line should read:
pythonpyprog.pybuild_ext--compiler=mingw32--inplace
This, however, does not solve the issue when using the pyximport method (seethe tutorial). Alternatively, the following patch can be applied.
NOTE: This is untested.
Open the file pyximport/pyxbuild.py and add the four lines marked with “+” atthe appropriate place.
Finally, if this does not work, create a file called “pydistutils.cfg” innotepad and give it the contents:
[build_ext]compiler=mingw32
Save this to the home directory, which can be found by typing at the commandprompt:
importosos.path.expanduser('~')
Explanations¶
What is the difference between a.pxd
and.pxi
file? When should either be used?¶
SHORTAnswer: You should always use .pxd files for declarations and .pxifiles only for code that you want to include.
MEDIUMAnswer: A .pxd files are lists of declarations, .pxi files aretextually included, and their use for declarations is a historical artifact ofthe way common declarations were shared before .pxd files existed.
LONGAnswer: A .pxd file is a declaration file, and is used to declareclasses, methods, etc. in a C extension module, (typically as implemented in a.pyx file of the same name). It can contain declarations only, i.e. noexecutable statements. One cancimport
things from .pxd files just as onewould import things in Python. Two separate modules cimporting from the same.pxd file will receive identical objects.
A .pxi file is an include file and is textually included (similar to the C#include
directive) and may contain any valid Cython code at the givenpoint in the program. It may contain implementations (e.g. common cdef inlinefunctions) which will be copied into both files. For example, this means thatif I have a class A declared in a.pxi, and both b.pyx and c.pyx doincludea.pxi
then I will have two distinct classes b.A and c.A. Interfaces to Clibraries (including the Python/C API) have usually been declared in .pxi files(as they are not associated to a specific module). It is also re-parsed atevery invocation.
Now thatcimport*
can be used, there is no reason to use .pxi files forexternal declarations.
What is better, a single big module or multiple separate modules?¶
Answer: In short, one big module is clumsy to handle but allows broaderoptimisations by the C compiler.
The compile time might actually decrease for multiple modules since the buildcan be parallelised. The “build_ext” command in distutils has a “-j” optionsince Py3.5. Also, smaller modules are usually faster to compile by the Ccompiler, because some optimisations may involve non-linear overhead.
The distribution size, and the size per module, will probably increase whensplitting a module because there are some things that Cython has to copy intoeach module. There is afeature request that would mitigatethis.
C calls between modules are slightly slower than C calls inside of a module,simply because the C compiler cannot optimise and/or inline them. You will haveto use shared .pxd declarations for them, which will then call through afunction pointer. If modules use a functional split, however, this should nothurt too much. It might still be a good idea to create a shared .pxd file (or.pxi) with inline functions for performance critical code that is used inmultiple modules.
When splitting an existing module, you will also have to deal with the APIchanges. Leaving some legacy imports here and there, or turning a module into apackage that merges the module namespaces back together via imports, mightprevent code breakage for users of your original module when you move namesaround and redistribute them across multiple modules.
What is the difference betweenPyObject*
andobject
?¶
Answer: A variable of typePyObject*
is a simple C pointer, just likevoid*
. It is not reference counted, which is sometimes referred to as aborrowed reference. Anobject
variable is an owned reference to a Pythonobject. You can convert one into the other by casting:
fromcpython.refcimportPyObjectpy_object=[1,2,3]cdefPyObject*ptr=<PyObject*>py_objectcdefobjectl=<object>ptr# this increases the reference count to the list
Note that the lifetime of the object is only bound to its owned references, notto any C pointers that happen to point to it. This means thatptr
in theexample above becomes invalid as soon as the last reference to the object dies:
py_object=[1,2,3]cdefPyObject*ptr=<PyObject*>py_objectpy_object=None# last reference to list dies here# ptr now points to a dead objectprint(<object>ptr)# expect a crash here!
Pointers are commonly used when passing objects through C callbacks, e.g.
cdefintcall_it_from_c(void*py_function,void*args):py_args=<tuple>argsifargsisnotNULLelse()return(<object>py_function)(*py_args)defpy_func(a,b,c):print(a,b,c)return-1args=[1,2,3]call_it_from_c(<PyObject*>py_func,<PyObject*>args)
Once again, care must be taken to keep the objects alive as long as anypointers to them are still in use.
Why does Cython not always give errors for uninitialized variables?¶
Answer: Cython does some static checks for variable initialization beforeuse during compile time, but these are very basic, as Cython has no definiteknowledge what paths of code will be taken at runtime:
Consider the following
deftestUnboundedLocal1():ifFalse:c=1printcdeftestUnboundedLocal2():printc
With CPython, both functions lead to the following exception:
NameError:globalname'c'isnotdefined
With Cython, the first variant prints “None”, the second variant leads to acompile time error. Both behaviours differ from CPython’s.
This is considered a BUG and will change in the future.
Why does a function with cdef’d parameters accept None?¶
Answer: It is a fairly common idiom in Python to useNone
as a way tomean “no value” or “invalid”. This doesn’t play well with C, asNone
is notcompatible with any C type. To accommodate for this, the default behavior isfor functions with cdefed parameters to also accept None. This behavior wasinherited from Pyrex, and while it has been proposed that it be changed, itwill likely stay (at least for a while) for backwards capability.
You have four choices for how to handleNone
in your code:
In Cython 3.x, use Python type annotations instead of Cython syntax. Python type annotations distinguish between
func(x:MyType)
andfunc(x:Optional[MyType])
, where the firstdisallowsNone
and the second explicitly allows it.func(x:MyType=None)
allows it as well because it is explicitly required by the provided default value.If you want to consider
None
invalid input, then you need to write code that checks for it, and raised an appropriate exception.If you want Cython to raise an exception if
None
is passed in for an extension type parameter, you can use thenotNone
declaration:deffoo(MyClassvalnotNone):<...>
which is a short-hand for
deffoo(MyClassval):ifvalisNone:raise<...><...>
You can also put
#cython:nonecheck=True
at the top of your file and all access will be checked for None, but it will slow things down, as it is adding a check on every access, rather that once on function call.
About the project¶
Is Cython a Python implementation?¶
Answer: Not officially, no. However, it compiles almost all existing Pythoncode, which gets it pretty close to a real Python implementation. The resultdepends on the CPython runtime, though, which we consider a major compatibilityadvantage. In any case, it is an official goal for Cython to compile regularPython code and run (most of) the normal Python test suite - obviously fasterthan CPython. ;-)
Is Cython faster than CPython?¶
Answer: For most things, yes. For example, a Cython compiled pybench runsmore than 30% faster in total, while being 60-90% faster on control structureslikeif-elif-else
andfor
-loops. We regularly run the tests from theCPython benchmark suite (which includes Django templates, 2to3, computationalbenchmarks and other applications) and most of them work out-of-the-box withoutmodifications or static typing, with a performance increase of 20-60%.
However the main advantage of Cython is that it scales very well to evengreater performance requirements. For code that operates heavily on commonbuiltin types (lists, dicts, strings), Cython can often speed up processingloops by factors. For numerical code, speed-ups of 100-1000 times compared toCPython are not unusual, and are achieved by simply adding static typedeclarations to performance critical parts of the code, thus trading Python’sdynamic typing for speed. As this can be done at any granularity in the code,Cython makes it easy to write simple Python code that is fast enough, and justtune the critical 5% of your code into maximum performance by using static Ctypes in just the right places.
What Python versions does Cython support?¶
Answer: From Cython 0.21 on, the supported versions are 2.6, 2.7 and 3.4+,with Python 2.6 being phased out implicitly due to lack of testingcapabilities. Cython 3.0 removes support for Python 2.6 completely and requireseither Python 2.7 or Python 3.4+. Python 2.x support is scheduled for removalin Cython 3.1, which will probably require Python 3.6 or later at the time ofits release.
The C code generated by Cython is portable and builds in all supported Pythonversions. All supported CPython release series are tested regularly. NewCPython versions are usually supported before they are released.
The source code that Cython compiles can use both Python 2 and Python 3 syntax,defaulting to Python 2 syntax in Cython 0.x and Python 3 syntax in Cython 3.xand later. When compiling Cython modules (.pyx files) in Python 2 mode, mostPython 3 syntax features are available by default if they do not interfere withPython 2 syntax (as in Python 2.7), but the general language semantics aredefined as in Python 2. When compiling Python modules (.py files), the specialCython syntax (such as thecdef
keyword) is not available. For both inputtypes, the language level can be set to Python 3 by either passing the “-3”option to the compiler, or by putting
# cython: language_level=3
at the top of the module file (within the first comment and before any code orempty lines). With Cython 3.x, compiling Python 2 code requires the option “-2”or the directivelanguage_level=2
. By default, with the Python 3 semanticsin Cython 3.0,print()
is a function, loop variables in list comprehensionsdo not leak into the outer scope, etc. This is equivalent tolanguage_level=3str
or the option--3str
. If you instead selectlanguage_level=3
, then, additionally, unprefixed strings are always unicodestrings.
What’s the license situation of Cython’s output?¶
Answer: You can use the output of Pyrex/Cython however you like (andlicense it how you like - be it BSD, public domain, GPL, all rights reserved,whatever).
More details: The Python License is different from the GPL used for GCC, forexample. GCC requires a special exception clause for its output as it islinked against the library part of GCC, i.e. against GPL software, whichtriggers the GPL restrictions.
Cython doesn’t do anything similar, and linking against Python is notrestricted by the Python License, so the output belongs to the User, no otherrights or restrictions involved.
Also, all of the copyright holders of Pyrex/Cython stated in mailing list thatpeople are allowed to use the output of Pyrex/Cython however they would like.
How do I cite Cython in an academic paper?¶
Answer: If you mention Cython, the simplest way to reference us is to addthe URL to our website in a footnote. You may also choose to reference oursoftware projectin a more formal way, such as
R.Bradshaw,S.Behnel,D.S.Seljebotn,G.Ewing,etal.,TheCythoncompiler,http://cython.org.
(the list of author names were taken from setup.py)
For a yet more formal citation, there is ajournalpaper on Cython.If you wish to cite it, here’s the Bibtex:
@ARTICLE{behnel2010cython,author={Behnel,S.andBradshaw,R.andCitro,C.andDalcin,L.andSeljebotn,D.S.andSmith,K.},journal={ComputinginScienceEngineering},title={Cython:TheBestofBothWorlds},year={2011},month=march-april,volume={13},number={2},pages={31-39},keywords={Cythonlanguage;Fortrancode;Pythonlanguageextension;numericalloops;programminglanguage;Clanguage;numericalanalysis;},doi={10.1109/MCSE.2010.118},ISSN={1521-9615},}
What is the relation between Cython and Pyrex?¶
Answer: Cython started originally based on a previous project called Pyrex,developed primarily by Greg Ewing.
Years later, Pyrex development has effectively stopped, whereas Cython has keptadding new features and support for new Python versions.
As of 2023, Pyrex is only of historical interest.