0

此代码片段在 python 3.6.4 下运行良好,但在 .pyx 文件中存在时会触发可移植性问题。我可以使用一些帮助来确定如何在 Cython 中最好地格式化 python 3.5.1+ 字节。

编辑:根据 DavidW 的评论改变这一点。

以下在 ipython 下的 python 3.6.4 中工作

def py_foo():
    bytes_1 = b'bytes 1'
    bytes_2 = b'bytes 2'

    return b'%(bytes_1)b %(bytes_2)b' % {
                    b'bytes_1': bytes_1,
                    b'bytes_2': bytes_2}

正如所希望的那样:

print(py_foo())

b'bytes 1 bytes 2'

使用 cython 对代码的唯一更改是函数名称、声明的返回类型和声明两个变量。

%load_ext Cython
# Cython==0.28

其次是:

%%cython
cpdef bytes cy_foo():
    cdef:
        bytes bytes_1, bytes_2

    bytes_1 = b'bytes 1'
    bytes_2 = b'bytes 2'

    return b'%(bytes_1)b %(bytes_2)b' % {
                    b'bytes_1': bytes_1,
                    b'bytes_2': bytes_2}

结果是:

Error compiling Cython file:
....
    return b'%(bytes_1)b %(bytes_2)b' % {
                                     ^
..._cython_magic_b0aa5be86bdfdf75b98df1af1a2394af.pyx:7:38: Cannot convert 'basestring' object to bytes implicitly. This is not portable.

-djv

4

1 回答 1

1

我不确定这是一个有用的答案还是只是一个更详细的诊断,但是:问题在于返回类型。如果你这样做:

cpdef cy_foo1(): # no return type specified
    # everything else exactly the same

然后它很高兴。如果你这样做

cpdef bytes cy_foo2():
    # everything else the same
    return bytes(b'%(bytes_1)b %(bytes_2)b' % {
                b'bytes_1': bytes_1,
                b'bytes_2': bytes_2})

然后它很高兴。如果你这样做

def mystery_function_that_returns_not_bytes():
    return 1

cpdef bytes cy_foo3():
    return mystery_function_that_returns_not_bytes()

然后它会愉快地编译,但会出现运行时异常(如您所料)


问题似乎是它知道bytes % something返回 abasestring但它不相信它会返回bytes并且不准备离开它直到运行时尝试(与它完全确定或完全不确定何时离开它直到运行)。

上面的例子展示了几种解决方法。就个人而言,我只是删除了返回类型——无论如何,键入 Python 对象不会给您带来很多好处bytes。您可能还应该将此作为错误报告给https://github.com/cython/cython/issues

于 2018-03-15T17:56:57.427 回答