我从csv文件中获取数据,使用它执行某些操作,然后将其写入文本模板。
当我遇到无法编码的字符时会出现问题。
例如,当我使用中文编写的值时,当我使用某种csv编辑器(例如LibreOffice Calc for Linux)打开它时,所选字段为空白。
但是当我在脚本中通过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
...
如何正确显示数据?还有一种方法可以跳过这些数据,例如可以尝试解码数据的东西,如果它不成功,则将其转换为空字符串。
附: try except
在此不起作用,因为mystring.encode('utf-8')
或mystring.encode('latin-1')
会对字符串进行编码,但仍然会将其作为垃圾输出。
修改
打印出问题行后,有问题值的输出如下:
{'Name': '\x1a \x1a\x1a', 'State': '\x1a\x1a\x1a'}
答案 0 :(得分:1)
\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)
答案 1 :(得分:0)
感谢@Andrea Corbellini,您的回答帮助我找到了解决方案。
def stringcheck(line):
for letter in line:
if letter not in string.printable:
return 0
return 1
但是,我不认为这是这种方式最蟒蛇的方式,所以任何有关如何做到这一点的建议都会非常感激。