cython的setup.py中的language_level有什么作用?

The*_*Cat 3 cython

如果设置language_level=2ext_modules = cythonize(extensions, language_level=2),那会发生什么变化?只是我编写的代码应该解释为Python2吗?

最终结果完全一样吗?

ead*_*ead 6

建立cython扩展程序分为两个步骤:

  1. 使用PythonX + cython-module foo.cfoo.pyx文件创建-file 。X可能是2.7、3.7或您喜欢的任何版本。
  2. 在编译器的帮助下创建相应的so文件(在Windows上为pyd),并包括PythonY和相应的共享库。这里Y不必一定是X,但是在大多数情况下YX它们是相同的。

生成的扩展可以与PythonY一起使用(它没有起到什么作用X)。

但是,仍然存在一个问题:原始pyx文件是在哪个Python版本中写入的?如果language_level未设置,则当前的Cython版本假定pyx文件是用版本编写的2(顺便说一句。对于IPython-%% cython-magic而言,情况并非如此,在该版本中将文件foo.c进行cython化)。

这种行为将来会改变,这是如果您使用cython>=0.29以下命令进行构建,则会看到有些恼人的警告的原因:

/Main.py:367:FutureWarning:未设置Cython指令'language_level',现在使用2(Py2)。这将在以后的版本中更改!档案:XXXXXX.pyx
tree = Parsing.p_module(s, pxd, full_module_name)

因此,您可以显式设置language_level,以便扩展名具有相同的行为,而不受其被cythonized的Python版本的影响。

有关不同行为的一些示例,请参见下面的示例。

使用language_level=3

%%cython -3
print("I'm", "not a tuple")
print(5/4) 
Run Code Online (Sandbox Code Playgroud)

结果是

I'm not a tuple
1.25  
Run Code Online (Sandbox Code Playgroud)

但使用language_level=2

I'm not a tuple
1.25  
Run Code Online (Sandbox Code Playgroud)

结果是

("I'm", 'not a tuple')   # yet a tuple!
1                        # integer division in Python2!
Run Code Online (Sandbox Code Playgroud)

显然,以上只是两个示例,还有更多区别(例如strunicode内容)。


其他显着差异之一是Python3禁用了 隐式相对导入,这意味着在包内部,我们不再使用隐式相对导入进行cimport。

%%cython -2
print("I'm", "not a tuple")
print(5/4) 
Run Code Online (Sandbox Code Playgroud)

但使用显式相对导入

("I'm", 'not a tuple')   # yet a tuple!
1                        # integer division in Python2!
Run Code Online (Sandbox Code Playgroud)

或绝对导入

# works with language_level=2
cimport other_local_cymodule
Run Code Online (Sandbox Code Playgroud)

通常,我会尽量避免将不同language_level版本和Python解释器版本混为一谈,因为这可能导致违反直觉的行为。

例如在下面的示例混合language_level=2和Python3中:

 # works with language_level=3,3str
 from . cimport other_local_cymodule
Run Code Online (Sandbox Code Playgroud)

对于功能,divide2Cython可以确保“正确”的Python2行为,但是如何执行除法取决于int-object的行为,该对象具有正常的Python3行为。