我有一个来自SQLAlchemy查询的decimal.Decimal
实例。由于我需要序列化对象,我创建了一个JSON序列化程序来处理Decimal
:
import decimal
class AlchemyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, decimal.Decimal):
return str(obj)
return json.JSONEncoder.default(self, obj)
不幸的是isinstance(obj, decimal.Decimal)
没有为实例返回True
,即使(在上面的default
方法中使用pdb):
obj.__class__ # => <class 'decimal.Decimal'>
blah = decimal.Decimal()
blah.__class__ # => <class 'decimal.Decimal'>
isinstance(obj, decimal.Decimal) # => False
isinstance(blah, decimal.Decimal) # => True
isinstance(obj, obj.__class__) # => True
我确实检查了两个实例引用的模块是同一个模块:
import inspect
inspect.getfile(obj.__class__) # => '/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/decimal.pyc'
inspect.getfile(blah.__class__) # => '/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/decimal.pyc'
我真的很想知道为什么这不起作用!
修改
事实证明,只有在AppEngine的dev_appserver.py
环境下运行时才会出现此问题。一个简单的:
isinstance(db.session.execute('SELECT amount FROM model LIMIT 1').fetchone()[0], decimal.Decimal)
当从控制台运行时,通过AppEngine dev_appserver和False
发出请求时返回True
。
答案 0 :(得分:3)
今天进入这个,并遇到了一个讨论过这个问题的旧mailing list post。
事实证明,此问题也已在on stackoverflow中得到解决。在此处粘贴答案以便于访问/减少stackoverflow服务器负载:
看来,十进制.Decimal类在Google App Engine SDK中的某个位置打了补丁(或重新加载了模块),这是在MySQL转换库导入十进制和导入十进制之间完成的。
幸运的是,我们可以通过更新MySQL转换表来解决这个问题:
from MySQLdb.constants import FIELD_TYPE
from MySQLdb.converters import conversions
import decimal
conversions[FIELD_TYPE.DECIMAL] = conversions[FIELD_TYPE.NEWDECIMAL] = decimal.Decimal
就是这样;上面的代码重置了MySQL类,你的JSON编码器类型检查成功。
替代方法是让您查找MySQLdb正在使用的类:
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, MySQLdb.converters.conversions[MySQLdb.constants.FIELD_TYPE.DECIMAL]):
return float(o)
return super(DecimalEncoder, self).default(o)