问题的描述
我必须将一些代码迁移到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 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")):
...该代码在Python 2上运行良好。但是在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必须返回像对象那样的字节
发布于 2015-03-10 13:14:35
一种选择是以二进制模式打开文件:
open("file.txt", "rb")这将创建一个返回字节序列的迭代器。
Python 3字符串被假定为Unicode,如果没有正确的编码/解码,它们不应该被解释为字节序列。如果您正在读取普通的ASCII文本,而不是二进制数据流,则还可以从Unicode转换为ASCII。请参阅PyUnicode_AsASCIIString()和相关函数。
发布于 2015-03-10 15:37:39
正如@casevh所指出的,在Python中,您需要确定数据是二进制还是文本。事实上,您正在迭代行,这使我认为后者是这样的。
def wrapper(stream):
for data in stream:
for i in data:
yield i在Python2中工作,因为迭代str将产生一个字符的字符串;在Python3中,对bytes对象的迭代将产生单个字节,这些字节是0- 255范围内的整数。通过一次使用范围和切片1字节/字符,您可以在Python 2和3中(并与上面代码的Python 2行为相同)获得相同的代码工作:
def wrapper(stream):
for data in stream:
for i in range(len(data)):
yield data[i:i + 1]在C扩展代码中也有一个错误:Parser_read包含3个参数,其中2个参数名为unused_x。只有一个带有METH_KEYWORDS注释的方法需要3个参数(PyCFunctionWithKeywords);所有其他参数(包括METH_NOARGS )都必须是带有2个参数(PyCFunction)的函数。
https://stackoverflow.com/questions/28960306
复制相似问题