rookieisme 2019-06-27
最近有个同事编译一个脚本后,脚本里面调用函数的地方出现了问题。
用一个简短的例子说明下:
py文件 a.py
内容如下:
def fn(a): print a fn(a=4) #出现问题在这一行
编译脚本build.sh
如下:
cython -D -2 --embed a.py gcc -c -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python2.7 -o a.o a.c gcc -I/usr/include/python2.7 -o a a.o -lpython2.7
前面的a.py用python a.py
执行是没有问题的,但是用cython编译成可执行文件后,执行就会出现如下错误:
Traceback (most recent call last): File "a.py", line 4, in init a fn(a=4) TypeError: fn() takes no keyword arguments
也就是在 fn(a=4)
的时候出现了问题。这个报错的意思是,这个fn不支持keyword参数,但是python是支持这种特性的。这不是冲突了?
我上网找了一下,也有人碰到这个问题:https://github.com/bottlepy/b...
这里有人指出:
This is actually an incorrect assertion, and there is a quite simply fix. By default, Cython compiles functions with 0 or 1 arguments, as special PyCFunction METH_O or METH_NOARGS. This functions do not accept keyword arguments. You can tell Cython to disable this optimization by changing the always_allow_keywords compiler directive to True (you can do it per function, per file or globally, check cython's documentation on how to do it). This issue happens actually in all web frameworks who use tricks like this.
cython编译器默认情况下会做一下优化:对于没有参数或只有一个参数的函数,会禁止keyword参数。
特地去差了下cython文档,确实如此:
always_allow_keywords (True / False) Avoid the METH_NOARGS and METH_O when constructing functions/methods which take zero or one arguments. Has no effect on special methods and functions with more than one argument. The METH_NOARGS and METH_O signatures provide faster calling conventions but disallow the use of keywords.
在这里只要开启always_allow_keywords选项,就可以解决问题。所以我在前面build.sh
里对cython 加了一个参数,效果如下:
cython -D -2 --directive always_allow_keywords=true --embed a.py
也就是增加了 --directive always_allow_keywords=true
,也就解决了问题。