1

我在使用 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
4

2 回答 2

2

正如评论中所解释的,你几乎肯定会做错这一切……但如果你真的需要做这样的事情,这里是如何简化它:

避免重复自己的一般解决方案是使用循环。您已经获得了 3 次相同的代码,唯一的区别是encoding, 所以循环三个编码。(在您的情况下,第三个循环根本没有传递 an encoding,因此您必须知道参数的默认值,但文档help会告诉您。)唯一的问题是您显然不想要处理第三种情况的异常;最简单的方法是在它们都失败时重新引发最后一个异常。

当我们这样做时:没有必要i像你那样预先“声明”;for循环将从 0 开始并擦除您放在那里的任何内容。这也意味着+2最后是错误的。但是首先有一种更简单的方法来获取可迭代的长度:只需将其输入到使用生成器表达式的东西中。ilen用 C 编写的自定义函数是理想的,但人们已经测试了各种不同的 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
于 2013-11-05T19:49:21.673 回答
1

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

open(fname, errors='ignore')

而且你永远不会例外。完毕。

于 2013-11-05T20:41:21.123 回答