I have a problem "cythonizing" a project written in python.
1. A python class (declared in file ) is instantiated, then "declared global" using setattr(__builtin__...) in file 中声明),然后在文件中使用 setattr(__builtin__...) “声明为全局”
2. A function declared in a module (file ) access this class instance by its global name ("globalclass"), and set some values. )中声明的 function 通过其全局名称(“globalclass”)访问此 class 实例,并设置一些值。
So the question is: How to cythonize a python module referring an object instance by its "global name" definned outside of the module with setattr(__builtin__...)?
I run python 2.7.15 on windows x86, with Cython 0.29.1.
The code provided below works fine when I run pure python:
python main.py
But cythonizing the file gives me an error: referring the global name of the class instance "globalclass".进行 cythonizing 会给我一个错误:的,指的是 class 实例“globalclass”的全局名称。
Here is the file , the definition of the class: ,class 的定义:
class Myclass:
def __init__(self):
self.value = ''
def setValue(self,text):
self.value = text
def printValue(self):
print self.value
Here is the file : this is the file I want to cythonize, but cython says "globalclass": :这是我想要 cythonize 的文件,但 cython 说的“globalclass”:
def setValue():
globalclass.setValue('test from module.py')
Here is the file (entry point) where the class is instantiated, and "declared global" using setattr(__builtin__...): (入口点),其中 class 被实例化,并使用 setattr(__builtin__...) “声明为全局”:
import __builtin__
from myclass import Myclass
from module import setValue
if __name__ == '__main__':
myclass = Myclass()
setattr(__builtin__, 'globalclass', myclass)
setValue()
globalclass.printValue()
And here is the file used to cythonize the all: :
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)
)
And here is the command I use to cythonize:
python setup.py build_ext --inplace
Here is the error message I get when cythonizing:
Error compiling Cython file:
------------------------------------------------------------
...
def setValue():
globalclass.setValue('test from module.py')^
------------------------------------------------------------
module.pyx:2:1: undeclared name not builtin: globalclass
This is an a place where Cython differs from Python (although it isn't documented hugely well). Essentially it assumes that it should be able to resolve all global names at compile-time, while what you're doing affects it at runtime.
Fortunately there's an option to turn this behaviour off . Simply add two lines to setup.py (as shown in the documentation above)
from Cython.Compiler import Options
Options.error_on_unknown_names = False
The cython compiler gets the information about python builtins at runtime.
So modifying 'builtins' before / while compiling will solve the problem without taking further action.
Ie use sitecustomize, usercustomize or some 'yourname'.pth to 'import my_builtin_patching_module' for the compile step. Make sure the import will take your original.py, not the compiled one, otherwise the imported.pyd/.so may be locked, preventing the compiler output.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.