1

I am new to cython(only use it for doing a little hw now). I use the following code to see a general idea of it in jupyter notebook.

%load_ext Cython
%%cython
def cfunc(int n):
    cdef int a = 0
    for i in range(n):
        a += i
    return a

print(cfunc(10))

However, it only prints out the result 45 once. When I run the print function, the cell doesn't show 45 anyone.

Is there any problems with the code? How can I make the cell prints out 45 just the same as a normal python code? Thanks.

Tony Lucas
  • 189
  • 1
  • 13

1 Answers1

2

When running %%cython-magic a lot happens under the hood. One can see parts of it when calling the magic in verbose mode, i.e. %%cython --verbose:

  1. A file called _cython_magic_b599dcf313706e8c6031a4a7058da2a2.pyx is generated. b599dcf313706e8c6031a4a7058da2a2 is the sha1-hash of the %%cython-cell, which is needed, for example, to be able to reload a %%cython-cell (see this SO-post).
  2. This file is cythonized and built to a c-extension called _cython_magic_b599dcf313706e8c6031a4a7058da2a2.
  3. This extension gets imported - this is the moment your code prints 45, and everything from this module is added to the global namespace.

If you execute the cell again, none of the above happens. This is because the %%Cython machinery can see that the cell has already executed and loaded - so nothing has to be done. The 3 steps above will be repeated if the cell is changed (because cell changes change the sha1-hash) or if the Python kernel running in Jupyter Lab (for example) is restarted.

To enforce that the steps above are performed, one has to pass --force (or -f) options to the %%cython-magic-cell, i.e.:

%%cython --force
...

# 45 is printed

However, because compiling Cython code may be time consuming, one might prefer something like the example given below.

%%cython
def cfunc(int n):
cdef int a = 0
for i in range(n):
    a += i
return a


def cython_main(int arg1):
    # Print the output from calling the funtion
    print(cfunc(arg1))

    # And/or return the output 
    return(cfunc(arg1))

NOTE:
The cython_main() function given above needs to be in the same cell with any def, cdef, or cpdef functions that it calls, but is invoked from a separate cell to solve the print issue raised in the OP.

Here's an example invoking the cython_main() function from a separate cell to pass a value of 10 to cfunc():

result = cython_main(10)

The result is:

45

This solves the print issue described in the OP because the call to cython_main() from outside the %%Cython cell forces cfunc() to be re-invoked even if the cell has been executed previously.

Aether
  • 85
  • 8
ead
  • 32,758
  • 6
  • 90
  • 153