Python 3兼容性问题
问题描述 我必须将一些代码迁移到Python 3。汇编成功地结束了。但我在运行时遇到了一个问题:Python 3兼容性问题,python,c,python-c-extension,Python,C,Python C Extension,问题描述 我必须将一些代码迁移到Python 3。汇编成功地结束了。但我在运行时遇到了一个问题: static PyObject* Parser_read(PyObject * const self, PyObject * unused0, PyObject * unused1) { //Retrieve bytes from the underlying data stream. //In this case, an iterator PyObject * const
static PyObject* Parser_read(PyObject * const self, PyObject * unused0, PyObject * unused1) {
//Retrieve bytes from the underlying data stream.
//In this case, an iterator
PyObject * const i = PyIter_Next(self->readIterator);
//If the iterator returns NULL, then no more data is available.
if(i == NULL)
{
Py_RETURN_NONE;
}
//Treat the returned object as just bytes
PyObject * const bytes = PyObject_Bytes(i);
Py_DECREF(i);
if( not bytes )
{
//fprintf(stderr, "try to read %s\n", PyObject_Str(bytes));
PyErr_SetString(PyExc_ValueError, "iterable must return bytes like objects");
return NULL;
}
....
}
在我的python代码中,我有如下内容:
for data in Parser(open("file.txt")):
...
该代码在Python2上运行良好。但在Python 3上,我得到了:
ValueError: iterable must return bytes like objects
更新
@casevh的解决方案在所有测试用例中都能很好地工作,除了一个:当我包装流时:
def wrapper(stream):
for data in stream:
for i in data:
yield i
for data in Parser(wrapper(open("file.txt", "rb"))):
...
我得到:
ValueError:iterable必须返回类似对象的字节一个选项是以二进制模式打开文件:
open("file.txt", "rb")
这将创建一个迭代器,返回字节序列
Python3字符串被假定为Unicode,如果没有正确的编码/解码,它们不应该被解释为字节序列。如果您正在读取纯ASCII文本,而不是二进制数据流,则还可以将Unicode转换为ASCII。请参阅
PyUnicode\u asasitring()
和相关函数。一个选项是以二进制模式打开文件:
open("file.txt", "rb")
这将创建一个迭代器,返回字节序列
Python3字符串被假定为Unicode,如果没有正确的编码/解码,它们不应该被解释为字节序列。如果您正在读取纯ASCII文本,而不是二进制数据流,则还可以将Unicode转换为ASCII。请参阅
PyUnicode\u asasitring()
和相关函数。一个选项是以二进制模式打开文件:
open("file.txt", "rb")
这将创建一个迭代器,返回字节序列
Python3字符串被假定为Unicode,如果没有正确的编码/解码,它们不应该被解释为字节序列。如果您正在读取纯ASCII文本,而不是二进制数据流,则还可以将Unicode转换为ASCII。请参阅
PyUnicode\u asasitring()
和相关函数。一个选项是以二进制模式打开文件:
open("file.txt", "rb")
这将创建一个迭代器,返回字节序列
Python3字符串被假定为Unicode,如果没有正确的编码/解码,它们不应该被解释为字节序列。如果您正在读取纯ASCII文本,而不是二进制数据流,则还可以将Unicode转换为ASCII。请参见
PyUnicode\u asasitring()
和相关函数。正如@casevh所指出的,在Python中,您需要确定数据是二进制的还是文本的。您正在迭代行的事实使我认为后者就是这样
在Python2中工作,因为迭代
str
将产生1个字符的字符串;在Python3中,对字节
对象进行迭代将生成0-255范围内的整数字节。通过使用范围并一次切片1个字节/字符,可以使代码在Python 2和Python 3中的工作方式相同(与上述代码的Python 2行为相同):
def wrapper(stream):
for data in stream:
for i in range(len(data)):
yield data[i:i + 1]
另外,您的C扩展代码中还有一个错误:
Parser\u read
接受3个参数,其中2个被命名为unused\u x
。只有带注释的方法接受3个参数(PyCFunctionWithKeywords
);所有其他函数,包括METH_NOARGS
必须是具有两个参数的函数(PyCFunction
)。正如@casevh所指出的,在Python中,您需要确定数据是二进制的还是文本。您正在迭代行的事实使我认为后者就是这样
在Python2中工作,因为迭代
str
将产生1个字符的字符串;在Python3中,对字节
对象进行迭代将生成0-255范围内的整数字节。通过使用范围并一次切片1个字节/字符,可以使代码在Python 2和Python 3中的工作方式相同(与上述代码的Python 2行为相同):
def wrapper(stream):
for data in stream:
for i in range(len(data)):
yield data[i:i + 1]
另外,您的C扩展代码中还有一个错误:
Parser\u read
接受3个参数,其中2个被命名为unused\u x
。只有带注释的方法接受3个参数(PyCFunctionWithKeywords
);所有其他函数,包括METH_NOARGS
必须是具有两个参数的函数(PyCFunction
)。正如@casevh所指出的,在Python中,您需要确定数据是二进制的还是文本。您正在迭代行的事实使我认为后者就是这样
在Python2中工作,因为迭代
str
将产生1个字符的字符串;在Python3中,对字节
对象进行迭代将生成0-255范围内的整数字节。通过使用范围并一次切片1个字节/字符,可以使代码在Python 2和Python 3中的工作方式相同(与上述代码的Python 2行为相同):
def wrapper(stream):
for data in stream:
for i in range(len(data)):
yield data[i:i + 1]
另外,您的C扩展代码中还有一个错误:
Parser\u read
接受3个参数,其中2个被命名为unused\u x
。只有带注释的方法接受3个参数(PyCFunctionWithKeywords
);所有其他函数,包括METH_NOARGS
必须是具有两个参数的函数(PyCFunction
)。正如@casevh所指出的,在Python中,您需要确定数据是二进制的还是文本。您正在迭代行的事实使我认为后者就是这样
在Python2中工作,因为迭代
str
将产生1个字符的字符串;在Python3中,对字节
对象进行迭代将生成0-255范围内的整数字节。通过使用范围并一次切片1个字节/字符,可以使代码在Python 2和Python 3中的工作方式相同(与上述代码的Python 2行为相同):
def wrapper(stream):
for data in stream:
for i in range(len(data)):
yield data[i:i + 1]
另外,您的C扩展代码中还有一个错误:
Parser\u read
接受3个参数,其中2个被命名为unused\u x
。只有带3 arg注释的方法