【问题标题】:Why there is a difference between 32 bit and 64 bit numpy/pandas为什么 32 位和 64 位 numpy/pandas 之间存在差异
【发布时间】:2016-12-25 22:22:56
【问题描述】:

我在 64 位 Fedora 机器上使用 numpy/pandas,在生产中他们推送到 32 位 Centos 机器并遇到json.dumps 错误。它正在抛出repr(0) is not Serializable

我尝试在 64 位 Centos 上进行测试,它运行得非常好。但是在 32 位(准确地说是 Centos 6.8)上它会引发错误。我想知道是否有人以前遇到过这个问题。

下面是64位Fedora,

Python 2.6.6 (r266:84292, Jun 30 2016, 09:54:10) 
[GCC 5.3.1 20160406 (Red Hat 5.3.1-6)] on linux4
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas as pd

>>> >>> a = pd.DataFrame([{'a':1}])
>>> 
>>> a
   a
0  1
>>> a.to_dict()
{'a': {0: 1}}
>>> import json
>>> json.dumps(a.to_dict())
'{"a": {"0": 1}}'

以下是 32 位 Centos

import json
import pandas as pd

a = pd.DataFrame( [ {'a': 1} ] )
json.dumps(a.to_dict())

Traceback (most recent call last):
  File "sample.py", line 5, in <module>
    json.dumps(a.to_dict())
  File "/usr/lib/python2.6/json/__init__.py", line 230, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.6/json/encoder.py", line 367, in encode
    chunks = list(self.iterencode(o))
  File "/usr/lib/python2.6/json/encoder.py", line 309, in _iterencode
    for chunk in self._iterencode_dict(o, markers):
  File "/usr/lib/python2.6/json/encoder.py", line 275, in _iterencode_dict
    for chunk in self._iterencode(value, markers):
  File "/usr/lib/python2.6/json/encoder.py", line 309, in _iterencode
    for chunk in self._iterencode_dict(o, markers):
  File "/usr/lib/python2.6/json/encoder.py", line 268, in _iterencode_dict
    raise TypeError("key {0!r} is not a string".format(key))
TypeError: key 0 is not a string

解决此问题的常用方法是什么?我不能为 json 使用自定义编码器,因为我用来推送此数据的库需要一个字典,并且它在内部使用 json 模块对其进行序列化并将其推送到网络上。

更新: Python 版本为 2.6.6,pandas 均为 0.16.1

【问题讨论】:

  • 这看起来不应该适用于任何一个版本。我猜系统运行的是不同的 Pandas 版本,其中一个版本有一个奇怪的 hack,使 0 表现得像某种整数字符串混合体。
  • @user2357112 它应该在两个版本上都可以工作。
  • OP 你忘了添加最重要的东西:32 位 centos 上的 Python 版本和它们两者上的 pandas 版本。
  • @AnttiHaapala Python 2.6.6 和 pandas 0.16.1 32 位和 64 位
  • @AnttiHaapala:嗯,你说得对。 json 模块将 dict 键强制转换为字符串,而不是引发 TypeError,至少在 2.7 上。 2.6 文档没有 2.7 文档对此的注释;不知道是不是json模块版本差异。

标签: python json pandas numpy 32bit-64bit


【解决方案1】:

我相信会发生这种情况是因为索引是一个大小与 Python int 不同的 numpy.intNN,并且这些索引本身并不是从一个转换到另一个。

比如,在我的 64 位 Python 2.7 和 Numpy 上:

>>> isinstance(numpy.int64(5), int)
True
>>> isinstance(numpy.int32(5), int)
False

然后:

>>> json.dumps({numpy.int64(5): '5'})
'{"5": "5"}'
>>> json.dumps({numpy.int32(5): '5'})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/json/__init__.py", line 243, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
TypeError: keys must be a string

您可以尝试将索引更改为numpy.int32numpy.int64int

>>> df = pd.DataFrame( [ {'a': 1}, {'a': 2} ] )
>>> df.index = df.index.astype(numpy.int32)  # perhaps your index was of these?
>>> json.dumps(df.to_dict())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/json/__init__.py", line 243, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
TypeError: keys must be a string

所以你可以尝试将索引类型更改为int32int64 或只是简单的 Python int

>>> df.index = df.index.astype(numpy.int64)
>>> json.dumps(df.to_dict())
'{"a": {"0": 1, "1": 2}}'

>>> df.index = df.index.astype(int)
>>> json.dumps(df.to_dict())
'{"a": {"0": 1, "1": 2}}'

【讨论】:

    猜你喜欢
    • 2010-12-18
    • 2011-05-15
    • 1970-01-01
    • 2010-09-21
    • 2011-04-02
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    • 2012-09-03
    相关资源
    最近更新 更多