如何检测 python 中的未解码字符?

How to detect undecoded characters in python?

我从 c​​sv 文件中获取数据,对其进行处理,然后将其写入文本模板。

遇到无法编码的字符时出现问题。

例如,当我遇到一个用中文写的值时,当我用某种 csv 编辑器(例如 Linux 的 LibreOffice Calc)打开它时,所选字段是空白的。

但是当我在我的脚本中通过 csv.reader 获取数据时,我可以看到它实际上是一个没有被正确解码的字符串。 当我尝试将它写入模板时,我得到了这个奇怪的 SUB 字符串。

这里是问题的分解:

for row in csv.DictReader(csvfile):
    # take value from the row and store it in a dictionary
    ....
    # take the values from the dictionary and write them to a template
    with open('template.txt', 'r+') as template:
        src = Template(template.read())
        content = src.substitute(rec)

    with open('myoutput.txt', 'w') as bill:
        bill.write(content)

template.txt 看起来像这样:

$name
$address
$city
...

所有这些都会生成这样的 txt 文件:

Bill
North Grove 14
Scottsdale
...

如果任何字典值是空的,例如空字符串 '',我的模板渲染函数会忽略该标记,例如,如果特定行中缺少 address 属性,则输出将是

Bill
Scottsdale
...

当我尝试用我的中文数据这样做时,我的函数确实写入了数据,因为有问题的字符串不为空。当我将它们写入模板时,最终结果如下所示:

    SUB
    SUB
    Hong Kong
    ...

如何正确显示我的数据?还有一种方法可以跳过该数据,例如可以尝试解码数据的方法,如果不成功,则将其转换为空字符串。 P.S。 try except 在这里不起作用,因为 mystring.encode('utf-8')mystring.encode('latin-1') 会对字符串进行编码,但它仍然会作为垃圾输出。

编辑

打印出问题行后,问题值的输出如下:

{'Name': '\x1a \x1a\x1a', 'State': '\x1a\x1a\x1a'}

\x1a就是ASCII substitute character。这就是您在输出中看到 "SUB" 的原因。此字符通常用作尝试解码字节但失败的程序的替换。

您的 CSV 文件不包含有效数据。可能它是从包含有效数据的源开始生成的,但文件本身不再包含有效数据。

只是猜测:也许,您是用 LibreOffice 打开文件然后保存的吗?


如果您想检查您的字符串是否包含不可打印的 ASCII 字符,请使用:

def is_printable(data):
    return all(c in string.printable for c in data)

如果要删除不可打印的 ASCII 字符:

def strip_unprintable(data):
    return ''.join(c for c in data if c in string.printable)

如果要处理 Unicode 字符串,则将 c in string.printable 替换为:

ord(c) > 0x1f and ord(c) != 0x7f and not (0x80 <= ord(c) <= 0x9f)

(归功于 What is the range of Unicode Printable Characters?

感谢@Andrea Corbellini,您的回答帮助我找到了解决方案。

def stringcheck(line):
    for letter in line:
        if letter not in string.printable:
            return 0
    return 1

但是我认为这不是最符合 Python 风格的方法,因此我们将不胜感激任何关于如何改进它的建议。