Python变音字符问题 - 需要mbcs,对所有字符都有更好的方法

时间:2013-11-05 19:31:20

标签: python utf-8 ansi mbcs

我在使用Python脚本打开包含变音字符的文件时出现问题。当然,我认为我可以使用unicode utf8修正,但不是这样......

我最终使用 mbcs (默认为cp1252)

然后我写了这篇声明,我希望写下更多的清洁工,

def len(fname):
i = -1
try:
    with open(fname, encoding='mbcs') as f:
        for i, l in enumerate(f):
            pass
except UnicodeDecodeError:
    try:
        i = -1
        with open(fname, encoding='utf8') as f:
            for i, l in enumerate(f):
                pass
    except UnicodeDecodeError:
        i = -1
        with open(fname) as f:
            for i, l in enumerate(f):
                pass
return i + 2 # 2 because it starts at -1 not 0

2 个答案:

答案 0 :(得分:2)

你几乎可以肯定这一切都是错误的,正如评论中所解释的那样......但如果你真的需要做这样的事情,这里有如何简化它:

避免重复自己的一般解决方案是使用循环。你有三次相同的代码,唯一的区别是encoding,所以循环使用三种编码。 (在您的情况下,第三个循环根本没有传递encoding,因此您必须知道参数的默认值,但the docshelp会告诉您唯一的皱纹是你显然不想在第三种情况下处理异常;最简单的方法是在最后一个异常失败的情况下重新加注。

虽然我们在这里:没有必要像你一样“预告”ifor循环将从0开始并删除你放在那里的任何东西。这也意味着最后的+2是错误的。但是有一种更简单的方法可以首先获得迭代的长度:只需将它提供给消耗生成器表达式的东西。用C编写的自定义ilen函数是理想的,但是人们已经测试了各种不同的Python实现,而sum(1 for _ in iterable)几乎和完美的解决方案一样快,而且很简单,所以它是最常用的习惯用法。如果您不明白这一点,请将其作为一个函数进行分解,并将其命名为lien,并为其提供一个很好的文档字符串和/或注释。或者只是pip install more-itertools,然后您就可以致电more_itertools.ilen(f)

无论如何,把它们放在一起:

def len(fname):
    for encoding in 'mbcs', 'utf8', None:
        try:
            with open(fname, encoding=encoding) as f:
                return sum(1 for line in f)
        except UnicodeDecodeError as e:
            pass
    raise e

答案 1 :(得分:1)

我并不完全清楚你想要的是什么:如果你只想计算线数,请忽略错误! - 这是非常安全的,因为几乎所有编码都使用相同的ASCII兼容行结尾(UTF-16除外)。

open(fname, errors='ignore')

你永远不会得到例外。完成。