为什么jupyter笔记本只打印一次cython结果?


问题内容

我是cython的新手(现在只用于做一点硬件)。我使用以下代码在jupyter笔记本中查看其一般概念。

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

print(cfunc(10))

但是,它只打印一次结果45。当我运行打印功能时,该单元格不会显示45个任何人。

代码有问题吗?我怎样才能使单元格打印出与普通python代码相同的45格?谢谢。


问题答案:

运行时,%%cython魔术发生在引擎盖下。在详细模式下调用魔术时,可以看到其中的一部分,即%%cython --verbose

  1. _cython_magic_b599dcf313706e8c6031a4a7058da2a2.pyx生成一个名为的文件。b599dcf313706e8c6031a4a7058da2a2%%cython-cell的sha1-hash,例如,它是重新加载%%cython-cell所必需的(请参阅此SO-post)。
  2. 该文件被cython化并构建为名为的c扩展名_cython_magic_b599dcf313706e8c6031a4a7058da2a2
  3. 此扩展名已导入-这是您的代码打印45的时刻,此模块中的所有内容都添加到了全局名称空间中。

当您再次执行该单元格时,以上内容均不会发生:给定机器可以看到的哈希值,该单元格已被执行并加载-
因此无所事事。仅当单元格的内容发生更改并因此更改其哈希值时,才会使用现金,而是执行上述3个步骤。

要强制执行上述步骤,必须将--force(或-f)选项传递给%%cython-magic-cell,即:

%%cython --force
...

# 45 is printed

但是,由于重新构建扩展非常耗时,因此可能更喜欢以下内容

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

# put the code of __main__ into a function
def cython_main():
   print(cfunc(10))

# execute the old main
cython_main()

现在调用cython_main()一个新的单元格,因此它以与普通python代码相同的方式重新评估。