Python 3.x cython和python3枚举的奇怪行为
我们在python3中有一大堆要移植的代码,我们在enumerate中面临着一种非常奇怪的行为Python 3.x cython和python3枚举的奇怪行为,python-3.x,python-2.7,cython,enumerate,Python 3.x,Python 2.7,Cython,Enumerate,我们在python3中有一大堆要移植的代码,我们在enumerate中面临着一种非常奇怪的行为 cdef char **c_argv c_argv = <char**>malloc(sizeof(char*) * len(args)) for idx, s in enumerate(args): if bytes != str: s = s.encode('utf-8') c_argv[idx] = s 这也不行 以下是我们测试的完整副本: 测试枚举
cdef char **c_argv
c_argv = <char**>malloc(sizeof(char*) * len(args))
for idx, s in enumerate(args):
if bytes != str:
s = s.encode('utf-8')
c_argv[idx] = s
这也不行
以下是我们测试的完整副本:
测试枚举.pyx
from libc.stdlib cimport malloc, free
from libc.string cimport const_char
def test_enumerate(args):
cdef char **c_argv
c_argv = <char**>malloc(sizeof(char*) * len(args))
for idx, s in enumerate(args):
if bytes != str:
s = s.encode('utf-8')
c_argv[idx] = s
for i in range(len(args)):
print("Set by enumerate",c_argv[i])
free(c_argv)
def test_loop_obj(args):
cdef char **c_argv
c_argv = <char**>malloc(sizeof(char*) * len(args))
idx=0
for s in (args):
if bytes != str:
s = s.encode('utf-8')
c_argv[idx] = s
idx = idx+1
for i in range(len(args)):
print("Set by loop on objects",c_argv[i])
free(c_argv)
def test_loop(args):
cdef char **c_argv
c_argv = <char**>malloc(sizeof(char*) * len(args))
for i in range(len(args)):
if bytes != str:
args[i] = args[i].encode('utf-8')
c_argv[i] = args[i]
for i in range(len(args)):
print("Set by loop on index",c_argv[i])
free(c_argv)
setup.py:
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("test_enumerate.pyx")
)
我们通过以下方式进行编译:
python/python3 setup.py build_ext --inplace
下面的输出说明了我们的问题:
$ python test.py
('Set by enumerate', 'salut')
('Set by enumerate', 'tu')
('Set by enumerate', 'vas')
('Set by enumerate', 'bien')
('Set by loop on objects', 'salut')
('Set by loop on objects', 'tu')
('Set by loop on objects', 'vas')
('Set by loop on objects', 'bien')
('Set by loop on index', 'salut')
('Set by loop on index', 'tu')
('Set by loop on index', 'vas')
('Set by loop on index', 'bien')
有人能解释我们在这里遗漏了什么吗
c_argv[idx] = s
这将c_argv[idx]
设置为指向s
数据的指针。指针仅在s
仍然存在时有效
s = s.encode('utf-8')
如果发生此行,则会创建一个新的编码的s
,导致先前编码的s
减少,因此可能会被释放
基本上,除非您了解(并且能够控制)c指针的生命周期,否则不要乱动它们
$ python3 test.py
('Set by enumerate', b'bien')
('Set by enumerate', b'bien')
('Set by enumerate', b'bien')
('Set by enumerate', b'bien')
('Set by loop on objects', b'bien')
('Set by loop on objects', b'bien')
('Set by loop on objects', b'bien')
('Set by loop on objects', b'bien')
('Set by loop on index', b'salut')
('Set by loop on index', b'tu')
('Set by loop on index', b'vas')
('Set by loop on index', b'bien')
c_argv[idx] = s
s = s.encode('utf-8')