Cython 无法导入和执行函数:存储临时 Python 引用的不安全 C 导数
Cython unable to import and execute a function: Storing unsafe C derivative of temporary Python reference
我是 Cython 的新手,只是想尝试使用一个简单的脚本。我无法从模块导入函数并在另一个文件中使用它,但如果我在同一个文件中声明该函数,它就可以正常工作。这里可能是什么问题。我错过了什么吗?
这是原始代码片段 (test_cy.pyx):
# test_cy.pyx
import json
cpdef char* say_hello():
message = json.dumps({"message": "Hello world"})
return message.encode()
cdef char* fn(int n):
cdef char* hello = say_hello()
return hello
def test():
cdef char* n = fn(1000)
print(n)
我可以运行它喜欢(编译后):
>>> import test_cy
>>> test_cy.test()
b'Hello world'
但是,如果我将 say_hello 函数移动到另一个文件 (utils.pyx):
# utils.pyx
import json
cpdef char* say_hello():
message = json.dumps({"message": "Hello world"})
return message.encode()
... 并将其导入到我原来的 test_cy.pyx 文件中,如下所示:
# test_cy.pyx
from utils import say_hello
cdef char* fn(int n):
cdef char* hello = say_hello()
return hello
def test():
cdef char* n = fn(1000)
print(n)
我无法编译它,因为我收到以下错误:
>>> python3 setup.py build_ext --inplace
...
Error compiling Cython file:
------------------------------------------------------------
...
from utils import say_hello
cdef char* fn(int n):
cdef char* hello = say_hello()
^
------------------------------------------------------------
test_cy.pyx:4:7: Storing unsafe C derivative of temporary Python reference
Traceback (most recent call last):
File "setup.py", line 11, in <module>
sources=["utils.pyx"]
File "/Users/asim/.pyenv/versions/3.6.9/lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1101, in cythonize
cythonize_one(*args)
File "/Users/asim/.pyenv/versions/3.6.9/lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1224, in cythonize_one
raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: test_cy.pyx
这是我的 setup.py 文件:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
setup(
ext_modules = cythonize([
Extension("test_cy",
sources=["test_cy.pyx"]
),
Extension("utils",
sources=["utils.pyx"]
)
])
)
请帮助我,因为像从另一个模块导入函数这样简单的事情不应该这么复杂。我可能会遗漏一些微不足道的东西。谢谢!
cpdef char* say_hello():
message = json.dumps({"message": "Hello world"})
return message.encode()
这是一场即将发生的灾难(尽管 Cython 似乎无法生成警告)。 char*
指向的数据由 message.encode()
的结果保存 - 临时 Python 对象在创建后立即销毁。因此你的char*
立即无效。
用 C 语言来思考这个问题:return 一个 char*
必须有人拥有 char*
,你应该 确切地 知道谁那个主人是。
在不对自己 allocating/deallocating 负责的情况下,没有一种简单、明智的方法可以 returning a char*
。除非您准备好这样做并且了解如何做到这一点,否则我建议您从代码中删除所有 char*
,只删除 return Python 个对象。
你得到的错误是因为 Cython 使用 cimport
来了解 Cython 函数。
from utils cimport say_hello
没有 cimport
它认为 say_hello
只是一个普通的 Python 函数 returning 一个普通的 Python 对象。但是,即使进行了此更改,您的代码仍然无效 - 您只是将错误移到了 Cython 看不到的地方。
我是 Cython 的新手,只是想尝试使用一个简单的脚本。我无法从模块导入函数并在另一个文件中使用它,但如果我在同一个文件中声明该函数,它就可以正常工作。这里可能是什么问题。我错过了什么吗?
这是原始代码片段 (test_cy.pyx):
# test_cy.pyx
import json
cpdef char* say_hello():
message = json.dumps({"message": "Hello world"})
return message.encode()
cdef char* fn(int n):
cdef char* hello = say_hello()
return hello
def test():
cdef char* n = fn(1000)
print(n)
我可以运行它喜欢(编译后):
>>> import test_cy
>>> test_cy.test()
b'Hello world'
但是,如果我将 say_hello 函数移动到另一个文件 (utils.pyx):
# utils.pyx
import json
cpdef char* say_hello():
message = json.dumps({"message": "Hello world"})
return message.encode()
... 并将其导入到我原来的 test_cy.pyx 文件中,如下所示:
# test_cy.pyx
from utils import say_hello
cdef char* fn(int n):
cdef char* hello = say_hello()
return hello
def test():
cdef char* n = fn(1000)
print(n)
我无法编译它,因为我收到以下错误:
>>> python3 setup.py build_ext --inplace
...
Error compiling Cython file:
------------------------------------------------------------
...
from utils import say_hello
cdef char* fn(int n):
cdef char* hello = say_hello()
^
------------------------------------------------------------
test_cy.pyx:4:7: Storing unsafe C derivative of temporary Python reference
Traceback (most recent call last):
File "setup.py", line 11, in <module>
sources=["utils.pyx"]
File "/Users/asim/.pyenv/versions/3.6.9/lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1101, in cythonize
cythonize_one(*args)
File "/Users/asim/.pyenv/versions/3.6.9/lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1224, in cythonize_one
raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: test_cy.pyx
这是我的 setup.py 文件:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
setup(
ext_modules = cythonize([
Extension("test_cy",
sources=["test_cy.pyx"]
),
Extension("utils",
sources=["utils.pyx"]
)
])
)
请帮助我,因为像从另一个模块导入函数这样简单的事情不应该这么复杂。我可能会遗漏一些微不足道的东西。谢谢!
cpdef char* say_hello():
message = json.dumps({"message": "Hello world"})
return message.encode()
这是一场即将发生的灾难(尽管 Cython 似乎无法生成警告)。 char*
指向的数据由 message.encode()
的结果保存 - 临时 Python 对象在创建后立即销毁。因此你的char*
立即无效。
用 C 语言来思考这个问题:return 一个 char*
必须有人拥有 char*
,你应该 确切地 知道谁那个主人是。
在不对自己 allocating/deallocating 负责的情况下,没有一种简单、明智的方法可以 returning a char*
。除非您准备好这样做并且了解如何做到这一点,否则我建议您从代码中删除所有 char*
,只删除 return Python 个对象。
你得到的错误是因为 Cython 使用 cimport
来了解 Cython 函数。
from utils cimport say_hello
没有 cimport
它认为 say_hello
只是一个普通的 Python 函数 returning 一个普通的 Python 对象。但是,即使进行了此更改,您的代码仍然无效 - 您只是将错误移到了 Cython 看不到的地方。