time.strptime() - 参数0必须是字符串,而不是字节。

4
显然我已经知道strftimestrptime不喜欢字节字符串作为参数,但是我在这里遇到了一些麻烦,因为我需要读取一个包含不同字符编码的文件内容,并将它们全部处理好,将每行文本中的时间部分发送到strptime()
一个快速的解决方法是拆分字符串,确保时间只包含数字和破折号,但是有没有可能以某种方式传递字节对象而不尝试找出编码来给strptime()使用呢?
with open('file.txt', 'rb') as fh:
    for line in fh:
        time.strptime(line, '%Y-%m-%d ...')

这显然会失败。我考虑使用repr(line),但这会导致字符串看起来像b'2014-01-07 ...',我可以去掉它。


你需要使用 .decode() 方法,但是如果不知道编码方式的话,这并不容易。 - Wooble
@Wooble:嗯,它符合日期时间模式,几乎肯定会符合ASCII。 - Martijn Pieters
它保存有不同的字符编码,我需要处理它们所有。 - Wooble
@Wooble:如果有任何行不使用ASCII,它们将无法保存%Y-%m-%d可以解析的日期。 - Martijn Pieters
2个回答

3

line 是一个字节串,因为你是以二进制模式打开文件的。你需要对该字符串进行解码;如果它是符合格式的日期字符串,你可以简单地使用 ASCII 编码:

 time.strptime(line.decode('ascii'), '%Y-%m-%d ...')

你可以添加一个'ignore'参数来忽略任何非ASCII字符,但有可能这行日期的格式也无法匹配。请注意,你不能传递一个包含比解析格式更多内容的值;带有其他文本的行不会被strptime()模式明确覆盖,无论使用哪种编解码器都不行。如果你的输入真的在编解码器方面变化很大,那么你需要以某种方式捕获异常。除了UTF-16或UTF-32之外,我不会指望你会遇到使用不同字节表示阿拉伯数字的编解码器。如果你的输入文件中真的混合了多字节和单字节编解码器,那么你就有了更大的问题,尤其是因为换行符处理将会被严重破坏。

“´ignore´”可能有效,因为问题出在字符串的时间/日期部分之后的内容,很可能是来自客户端的日志条目与大多数日志所包含的标准英语语言设置不同。而且由于我主要关注时间/日期,所以可以使用“´ignore´”,让字符串在结尾处保持“破损”,因为日期仍然完整,谢谢!这很可能解决了问题。 - Torxed

0

在读取文件时,您应该对数据进行解码:

import codecs
with codecs.open('file.txt', encoding='utf8') as fh:
    for line in fh:
        time.strptime(line, '%Y-%m-%d ...')

尽早解码内容总是更好的。

同时,请查看http://docs.python.org/2/library/codecs.html#codecs.open


这可能是一个好主意,但我担心某些行会由于某些字节数据无法使用utf-8表格进行转换而崩溃。不要问我是哪个字符,因为我还不太确定,因为找到导致此问题的字符需要大约半天的文件解析。当我注意到这个问题时,我没有调试输出(我很抱歉)。:) - Torxed
你可以按照文档中的说明,使用errors=(replace|ignore)来处理错误。 - gawel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接