Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cython code inside Python code

Tags:

python

cython

There are several ways of using Cython with Python.

  • First version (standard): you write your Cython code mylib.pyx, then you run this setup.py:

    from distutils.core import setup
    from Cython.Build import cythonize
    setup(ext_modules = cythonize("mylib.pyx"))

    that compiles it into a .pyd file, and then, in the main myprogram.py, you do import mylib.

    That's the standard way of working with Cython.

  • Second version ("on the fly compiling, with pyximport") :

    You write mylib.pyx, and you don't need any setup.py, you just do this in the main Python code:

    import pyximport; pyximport.install()
    import mylib

    That's it! The compilation will be done on the fly on the startup of the Python program!

Question:

Is there a "third version" ("easier on the fly compiling"):

# myprogram.py

import pyximport
pyximport.compile("""
      # Here is directly the Cython code inserted in the main Python code
      def mycythonfunction(int a, int b):
          cdef int i, j, 
      ...
      """)

res = mycythonfunction(3, 2)

i.e. with the Cython code directly inserted in the main Python code?

like image 432
Basj Avatar asked May 14 '15 14:05

Basj


2 Answers

The pure Python mode allows to use a decorator for type decelerations. You can use the same source with pure Python and with Cython.

For example:

@cython.locals(a=cython.double, b=cython.double)
def foo(a, b):
    return a + b
like image 154
Mike Müller Avatar answered Nov 07 '22 04:11

Mike Müller


A third way is to use cythonmagic in IPython notebook (see http://docs.cython.org/src/quickstart/build.html#using-the-ipython-notebook). Obviously that's designed to be used interactively, which may not be what you want.

If you look at what it does (the source code is in https://github.com/cython/cython/tree/master/Cython/Build) it creates a .pyx file in the current working directory with a "random" md5hash based name, and then uses pyximport to import that module. (It also messes around with locals and globals to ensure they're preserved).

You can access this mechanism yourself though Cython.Build.Inline. (I suspect this isn't meant to be a public interface, so it may change unexpectedly). Example:

from Cython.Build import Inline
Inline.cython_inline("""a=5
print a""",locals={},globals={})

# prints a bunch of lines about what it's compiling
# prints 5
# returns a dictionary of {'a'=5 }

Edit:

I should have recommended 'cython.inline' (which just forwards to Cython.Build.Inline.compile_inline) and does look to be documented and also 'cython.compile' which can be used as a decorator to compile an individual function (although you can't use any non-python keywords in that function.

like image 42
DavidW Avatar answered Nov 07 '22 06:11

DavidW