0

我正在尝试使用以下代码(在 web2py 中)读取 csv 文件并将其转换为 json 对象:

import csv
import json

originalfilename, file_stream = db.tablename.file.retrieve(info.file) 
file_contents =   file_stream.read()

csv_reader = csv.DictReader(StringIO(file_contents))
json = json.dumps([x for x in csv_reader])

这会产生以下错误:

“utf8”编解码器无法解码位置 1 中的字节 0xa0:无效的起始字节

显然,处理 .csv 文件中的空格存在问题。问题似乎源于 json.dumps() 行。从那时起的追溯:

Traceback (most recent call last):
  File ".../web2py/gluon/restricted.py", line 212, in restricted
    exec ccode in environment
  File ".../controllers/default.py", line 2345, in <module>
  File ".../web2py/gluon/globals.py", line 194, in <lambda>
    self._caller = lambda f: f()
  File ".../web2py/gluon/tools.py", line 3021, in f
    return action(*a, **b)
  File ".../controllers/default.py", line 697, in generate_vis
    request.vars.json = json.dumps(list(csv_reader))
  File "/usr/local/lib/python2.7/json/__init__.py", line 243, in dumps
    return _default_encoder.encode(obj)
  File "/usr/local/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xa0 in position 1: invalid start byte

有关如何解决此问题的任何建议,或将 csv 文件(包含标头;使用 StringIO)转换为不会产生类似并发症的 json 对象的其他方法?谢谢你。

4

3 回答 3

3

csv模块(在 Python 2 下)是纯粹基于字节的;你从中得到的所有字符串都是字节。然而 JSON 是基于 Unicode 字符的,因此当您尝试将从 CSV 获得的字节写出到 JSON 时存在隐式转换。Python 对此猜测为 UTF-8,但您的 CSV 文件不是 UTF-8 - 它可能是 Windows 代码页 1252(西欧 - 只是不太像 ISO-8859-1)。

一个快速的解决方法是转码您的输入 ( file_contents= file_contents.decode('windows-1252').encode('utf-8')),但您可能并不想依赖json猜测特定的编码。

最好在从 CSV 读取字符串时显式解码您的字符串。然后JSON就能应付他们OK了。不幸csv的是没有内置解码(至少在这个 Python 版本中),但你可以手动完成:

class UnicodeDictReader(csv.DictReader):
    def __init__(self, f, encoding, *args, **kwargs):
        csv.DictReader.__init__(self, f, *args, **kwargs)
        self.encoding = encoding
    def next(self):
        return {
            k.decode(self.encoding): v.decode(self.encoding)
            for (k, v) in csv.DictReader.next(self).items()
        }

csv_reader = UnicodeDictReader(StringIO(file_contents), 'windows-1252')
json_output = json.dumps(list(csv_reader))

事先不知道会出现什么样的编码

好吧,这是一个更大的问题,因为不可能准确地猜测文件的编码方式。如果您想支持非ASCII 字符正确。

于 2013-07-08T16:55:30.210 回答
2

尝试用你的最后一行替换

json = json.dumps([x.encode('utf-8') for x in csv_reader])
于 2013-07-07T18:49:03.557 回答
1

在文件内容上运行 unidecode 似乎可以解决问题:

from isounidecode import unidecode

...

file_contents =   unidecode(file_stream.read())

...

感谢大家!

于 2013-07-07T19:42:17.137 回答