我在使用 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
最佳答案
正如评论中所解释的那样,您几乎肯定会做错这一切......但如果您确实需要做这样的事情,以下是如何简化它:
避免重复的一般解决方案是使用循环。您已获得相同的代码三次,唯一的区别是编码
,因此改为循环三种编码。 (在您的情况下,第三个循环根本没有传递 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
关于Python 元音变音字符问题 - 需要 mbcs ,是否有更好的方法处理所有字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19797267/