Python 将Unicode流重新编码为Ascii忽略错误

Python 将Unicode流重新编码为Ascii忽略错误,python,python-2.7,encoding,stream,codec,Python,Python 2.7,Encoding,Stream,Codec,我试图获取一个包含奇数字符的Unicode文件流,并用一个流读取器将其包装,该读取器将其转换为Ascii,忽略或替换所有无法编码的字符 我的流看起来像: "EventId","Rate","Attribute1","Attribute2","(。・ω・。)ノ" ... 我尝试动态更改流,如下所示: import chardet, io, codecs with open(self.csv_path, 'rb') as rawdata: detected = chardet.detec

我试图获取一个包含奇数字符的Unicode文件流,并用一个流读取器将其包装,该读取器将其转换为Ascii,忽略或替换所有无法编码的字符

我的流看起来像:

"EventId","Rate","Attribute1","Attribute2","(。・ω・。)ノ"
...
我尝试动态更改流,如下所示:

import chardet, io, codecs

with open(self.csv_path, 'rb') as rawdata:
    detected = chardet.detect(rawdata.read(1000))

detectedEncoding = detected['encoding']
with io.open(self.csv_path, 'r', encoding=detectedEncoding) as csv_file:
    csv_ascii_stream = codecs.getreader('ascii')(csv_file, errors='ignore')
    log( csv_ascii_stream.read() )
"EventId","Rate","Attribute1","Attribute2","(?????)?"
...
日志
行上的结果是:
UnicodeEncodeError:“ascii”编解码器无法对位置36-40中的字符进行编码:序号不在范围(128)
内,即使我使用
errors='ignore'显式构造了StreamReader

我希望生成的流(读取时)如下所示:

import chardet, io, codecs

with open(self.csv_path, 'rb') as rawdata:
    detected = chardet.detect(rawdata.read(1000))

detectedEncoding = detected['encoding']
with io.open(self.csv_path, 'r', encoding=detectedEncoding) as csv_file:
    csv_ascii_stream = codecs.getreader('ascii')(csv_file, errors='ignore')
    log( csv_ascii_stream.read() )
"EventId","Rate","Attribute1","Attribute2","(?????)?"
...
或者,
“EventId”、“Rate”、“Attribute1”、“Attribute2”和“()”
(使用
“忽略”
而不是
“替换”

为什么会发生异常呢


我已经看到了很多关于解码字符串的问题/解决方案,但我的挑战是在读取流时更改流(使用
.next()
),因为文件可能太大,无法使用
.read()

一次加载到内存中。您混淆了编码和解码方面

对于解码,你做得很好。您可以将其作为二进制数据打开,
chardet
第一个1K,然后使用检测到的编码以文本模式重新打开

但是,您正试图通过使用将已解码的数据进一步解码为ASCII。该函数返回一个函数,该函数对来自流的数据进行解码。那是行不通的。您需要将该数据编码为ASCII

但不清楚为什么要使用
编解码器
流解码器或编码器,而您只需要一次性编码一个文本块,以便记录它。为什么不直接调用
encode
方法呢

log(csv_file.read().encode('ascii', 'ignore'))
如果您想要一些可以用作行的惰性iterable,您可以构建一些完全通用的东西,但只需执行文档中的
UTF8Recorder
示例就简单多了:

或者,更简单地说:

with io.open(self.csv_path, 'r', encoding=detectedEncoding) as csv_file:
    csv_ascii_stream = (line.encode('ascii', 'ignore') for line in csv_file)

我参加聚会有点晚了,但这里有一个替代解决方案,使用:


如果您需要灵活地调用返回的流上的
read()
/
readlines()
/
seek()
/
tell()
等,我想您可能需要使用此选项。如果您只需要在流上迭代,则提供的生成器表达式abarnert更简洁。

为什么不直接使用
io.open(self.csv_path,'r',encoding='ascii',errors='ignore')
呢?@dano我的印象是,如果我将UTF-16文件作为ascii打开,每8位将被错误地解释为一个字符,而不是每16次,整个文件将被误读。我的目标是以正确的编码读取该文件,然后动态地将其转换为ascii流。感谢您阅读本文。该日志仅用于调试目的,以便我可以看到我的读者所说的内容。我希望在流中执行与您正在执行的操作(重新编码为ascii)相同的操作。这可能吗?我已经按照你的建议做了(将
getreader
转换为
getwriter
),现在
ascii_流。read()
只是返回原始流(
EventId,Rate,Attribute1,Attribute2,(?)ノ...即无效的ASCII)。我是否错过了其他步骤?(就像从作者的作品中开始一个新的读者?@Alain:当然是这样。只是不能使用解码阅读器。如果你能准确地展示你想做什么,我可以告诉你怎么做。但是您可能只想看看
csv
文档中的示例,或者我认为
Unicode HOWTO
中有一些示例,直到您了解这个想法。我的最终目标是通过
csv.reader
运行流,它只接受ascii流。我已经查看了UTF8Recoder,但很难确定流在什么时候从原始编码转换为所需的编码(在我的例子中是Ascii,但在这里似乎是UTF8)。行
csv\u Ascii\u stream=(line.encode('Ascii','ignore')表示csv\u文件中的行)
似乎已经起作用了!非常感谢你!