我正在尝试从 PyQt4 QTableWidget
创建一个 csv 格式的文本文件。我想用 UTF-8 编码编写文本,因为它包含特殊字符。我使用以下代码:
import codecs
...
myfile = codecs.open(filename, 'w','utf-8')
...
f = result.table.item(i,c).text()
myfile.write(f+";")
它一直有效,直到单元格包含特殊字符。我也试过
myfile = open(filename, 'w')
...
f = unicode(result.table.item(i,c).text(), "utf-8")
但它也会在出现特殊字符时停止。我不知道我做错了什么。
myfile.write(u"%s"&f+";")
从你的 shell 运行:
pip2 install unicodecsv
并且(与原始问题不同)假设您使用的是 Python 的内置 csv
模块,请在代码中将
import csv
转换为
import unicodecsv as csv
。
writer = csv.writer(out, dialect='excel', encoding='utf-8')
,并使用 open(...
创建文件处理程序,not codecs.open(...
。
对我来说,Python 2 CSV 模块文档中的 UnicodeWriter
类并没有真正起作用,因为它破坏了 csv.writer.write_row()
接口。
例如:
csv_writer = csv.writer(csv_file)
row = ['The meaning', 42]
csv_writer.writerow(row)
有效,同时:
csv_writer = UnicodeWriter(csv_file)
row = ['The meaning', 42]
csv_writer.writerow(row)
将抛出 AttributeError: 'int' object has no attribute 'encode'
。
由于 UnicodeWriter
显然希望所有列值都是字符串,我们可以自己转换这些值并使用默认的 CSV 模块:
def to_utf8(lst):
return [unicode(elem).encode('utf-8') for elem in lst]
...
csv_writer.writerow(to_utf8(row))
或者我们甚至可以对 csv_writer 进行猴子补丁以添加 write_utf8_row
函数 - 练习留给读者。
Python 文档中的示例展示了如何编写 Unicode CSV 文件:http://docs.python.org/2/library/csv.html#examples
(这里不能复制代码,因为它受版权保护)
对于 python2,您可以在 csv_writer.writerows(rows)
之前使用此代码
此代码不会将整数转换为 utf-8 字符串
def encode_rows_to_utf8(rows): encoded_rows = [] for row in rows: encoded_row = [] for value in row: if isinstance(value, basestring): value = unicode(value).encode("utf-8") encoded_row.append(value) encoded_rows.append(encoded_row) return encoded_rows
我尝试使用 Bojan 的建议,但它把所有 None 单元格变成了单词 None 而不是空白,并将浮点数渲染为 1.231111111111111e+11,也许还有其他烦恼。另外,我希望我的程序同时在 Python3 和 Python2 下运行。所以,我最终把程序放在了顶部:
try:
csv.writer(open(os.devnull, 'w')).writerow([u'\u03bc'])
PREPROCESS = lambda array: array
except UnicodeEncodeError:
logging.warning('csv module cannot handle unicode, patching...')
PREPROCESS = lambda array: [
item.encode('utf8')
if hasattr(item, 'encode') else item
for item in array
]
然后将所有 csvout.writerow(row)
语句更改为 csvout.writerow(PREPROCESS(row))
我本可以使用测试 if sys.version_info < (3,):
而不是 try
语句,但这违反了“鸭子打字”。我可能会重新访问它并使用 with
语句正确编写第一个单行代码,以摆脱悬空的打开文件和 writer
,但随后我必须使用 ALL_CAPS 变量名,否则 pylint 会抱怨......无论如何都应该收集垃圾,并且无论如何只在脚本运行时持续。
一个非常简单的技巧是使用 json 导入而不是 csv。例如,而不是 csv.writer 只需执行以下操作:
fd = codecs.open(tempfilename, 'wb', 'utf-8')
for c in whatever :
fd.write( json.dumps(c) [1:-1] ) # json dumps writes ["a",..]
fd.write('\n')
fd.close()
基本上,给定正确顺序的字段列表,json 格式的字符串与 csv 行相同,除了分别位于开头和结尾的 [ 和 ] 。 json 似乎对 python 2 中的 utf-8 很健壮。 *
不定期副业成功案例分享
writerow
的内容不是 utf-8 怎么办?它会起作用吗?sys.stdout
那么在这种情况下内容如何是 utf8 呢?