【问题标题】:How to cythonize global __builtin__ objects?如何 cythonize 全局 __builtin__ 对象?
【发布时间】:2019-10-04 12:04:49
【问题描述】:

我在“cythonizing”一个用 python 编写的项目时遇到问题。

1. python 类(在文件 myclass.py 中声明)被实例化,然后在文件 main.py 中使用 setattr(__builtin__...) “声明为全局”
2. 在模块(文件module.py)中声明的函数通过其全局名称(“globalclass”)访问该类实例,并设置一些值。

所以问题是:如何通过在模块外部使用 setattr(__builtin__...) 定义的“全局名称”引用对象实例的 python 模块?

我在 windows x86 上运行 python 2.7.15,使用 Cython 0.29.1。

当我运行纯 python 时,下面提供的代码可以正常工作:

python main.py


但是 cythonizing 文件 module.py 给了我一个错误:undeclared name not builtin 引用类实例“globalclass”的全局名称。

这里是文件myclass.pyx,类的定义:

class Myclass:
    def __init__(self):
        self.value = ''

    def setValue(self,text):
        self.value = text

    def printValue(self):
        print self.value


这是文件 module.pyx:这是我要 cythonize 的文件,但 cython 说 未声明的名称不是内置的“globalclass”:

def setValue():
    globalclass.setValue('test from module.py')


这是类被实例化的文件 main.py(入口点),并使用 setattr(__builtin__...)“声明为全局”:

import __builtin__
from myclass import Myclass
from module import setValue

if __name__ == '__main__':
    myclass = Myclass()
    setattr(__builtin__, 'globalclass', myclass)
    setValue()
    globalclass.printValue()


这是用于 cythonize 的文件 setup.py

from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension

cyextensions = [
    Extension(name='myclass', sources=['myclass.pyx']),
    Extension(name='module', sources=['module.pyx']),
    ]

setup(name='test',
      version = '0.0.1',
      description = 'test',
      packages = ['test'],
      ext_modules = cythonize(cyextensions)
)

这是我用来 cythonize 的命令:

python setup.py build_ext --inplace

这是我在 cythonizing 时收到的错误消息:

Error compiling Cython file:
------------------------------------------------------------
...
def setValue():
        globalclass.setValue('test from module.py')^
------------------------------------------------------------

module.pyx:2:1: undeclared name not builtin: globalclass

【问题讨论】:

    标签: python python-2.7 cython cythonize


    【解决方案1】:

    这是 Cython 与 Python 不同的地方(尽管没有很好地记录它)。本质上,它假定它应该能够在编译时解析所有全局名称,而您正在做的事情会在运行时影响它。

    Fortunately there's an option to turn this behaviour off。只需在 setup.py 中添加两行(如上面的文档所示)

    from Cython.Compiler import Options
    Options.error_on_unknown_names = False
    

    【讨论】:

      【解决方案2】:

      cython 编译器在运行时获取有关 python 内置函数的信息。
      因此在编译之前/同时修改'builtins'将解决问题而无需采取进一步行动。
      即使用 sitecustomize、usercustomize 或一些 'yourname'.pth 来 'import my_builtin_patching_module' 用于编译步骤。 确保导入将采用您的原始 .py,而不是编译后的, 否则导入的 .pyd/.so 可能会被锁定,从而阻止编译器输出。

      【讨论】:

        猜你喜欢
        • 2016-05-09
        • 2016-02-16
        • 1970-01-01
        • 2012-04-11
        • 2019-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多