【发布时间】:2011-08-11 02:21:27
【问题描述】:
我有一个包含数百个模块的 Python 项目。在 Python 2.6 中,源文件(模块)的编码必须是 ASCII,除非 存在显式编码声明。有没有一种简单的方法来找出哪些 python 模块包含非 ASCII 字符?以便我更正它们。
问候,
【问题讨论】:
标签: python search character-encoding module ascii
我有一个包含数百个模块的 Python 项目。在 Python 2.6 中,源文件(模块)的编码必须是 ASCII,除非 存在显式编码声明。有没有一种简单的方法来找出哪些 python 模块包含非 ASCII 字符?以便我更正它们。
问候,
【问题讨论】:
标签: python search character-encoding module ascii
看看chardet python 包。您可以使用与 agf 相同的 os.walk 方法并调用 chardet.detect 方法并标记不是 ASCII(或具有较低置信度值)的文件。
这确实为错误留下了一些空间,所以如果您想更确定,您还可以扫描每个文件中不太可能出现在 python 文件中的字符(非字母数字、非标点符号等)。但是,这不会检测到与两个 7 位、零填充的 ascii 字符(即U+16705 AA)具有相同值的 UTF-16 字符之类的东西。
也就是说,如果您要排除的字符来自有限数量的字符集,您应该能够很有把握地找到它们。
【讨论】:
open(filename).read().decode("ascii")
如果这引发了 UnicodeDecodeError,则说明里面有一些非 ascii 字符
正如 Dana 所说,这不足以保证文件不是 UTF-16 或类似文件
【讨论】:
不是很快,但它会工作。它适用于任何与 ASCII 兼容的编码,例如 UTF-8、Latin-1 等,但不适用于 UTF-16。
def find_non_ascii(packagedir):
for filepath in os.walk(packagedir):
if not filepath[-1].endswith('.py'):
continue
filepath = os.path.join(*filepath)
for line in open(filepath):
for char in line:
if ord(char) > 127:
yield filepath
doublebreak = True
break
else:
doublebreak = False
if doublebreak:
break
或
def find_non_ascii(packagedir):
for filepath in os.walk(packagedir):
if not filepath[-1].endswith('.py'):
continue
filepath = os.path.join(*filepath)
try:
open(filepath, 'rb').read().decode('ascii')
except:
yield filepath
编辑:第二个版本可能更快。
【讨论】:
ord(127) 测试只会排除扩展的 ascii 字符。多字节编码中的 char 值集合与两个连续的 7 位 ascii 字符的值之间存在交集。