我在使用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
答案 0 :(得分:2)
你几乎可以肯定这一切都是错误的,正如评论中所解释的那样......但如果你真的做需要做这样的事情,这里有如何简化它:
避免重复自己的一般解决方案是使用循环。你有三次相同的代码,唯一的区别是encoding
,所以循环使用三种编码。 (在您的情况下,第三个循环根本没有传递encoding
,因此您必须知道参数的默认值,但the docs或help
会告诉您唯一的皱纹是你显然不想在第三种情况下处理异常;最简单的方法是在最后一个异常失败的情况下重新加注。
虽然我们在这里:没有必要像你一样“预告”i
。 for
循环将从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')
你永远不会得到例外。完成。