简体   繁体   English

isinstance在AppEngine中不适用于Decimal

[英]isinstance not working for Decimal in AppEngine

I have an instance of decimal.Decimal which comes from an SQLAlchemy query. 我有一个decimal.Decimal实例,它来自SQLAlchemy查询。 As I need to serialize the object, I have created a JSON serializer to deal with the 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)

The unfortunate thing is that the isinstance(obj, decimal.Decimal) does not return a True for the instance, even though (using pdb in the default method above): 不幸的是,即使(在上面的default方法中使用pdb isinstance(obj, decimal.Decimal)isinstance(obj, decimal.Decimal)也不会为实例返回True

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

I did check that the module both instances refer to is the same module: 我确实检查了两个实例引用的模块是同一个模块:

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'

I would really love to understand why this is not working! 我真的很想知道为什么这不起作用!

EDIT 编辑

It turns out that the issue only occurs when running under AppEngine's dev_appserver.py environment. 事实证明,只有在AppEngine的dev_appserver.py环境下运行时才会出现此问题。 A simple: 一个简单的:

isinstance(db.session.execute('SELECT amount FROM model LIMIT 1').fetchone()[0], decimal.Decimal)

returns False when making a request via the AppEngine dev_appserver and True when run from the console. 通过AppEngine dev_appserver发出请求时返回False ,从控制台运行时返回True

Ran into this today, and came across an old mailing list post that discussed this. 今天进入这个,并遇到了一个旧的邮件列表帖子 ,讨论了这一点。

Turns out this question has also been addressed on stackoverflow previously as well. 事实证明,此问题也已在stackoverflow上得到解决。 Pasting the answer here for ease of access / reduced stackoverflow server load: 在此处粘贴答案以便于访问/减少stackoverflow服务器负载:


It appears that the decimal.Decimal class is patched somewhere in the Google App Engine SDK (or the module is reloaded), and this is done between the MySQL conversion library importing decimal and you importing the same. 似乎decimal.Decimal类在Google App Engine SDK中的某个位置打了补丁(或者重新加载了模块),这是在MySQL转换库导入小数和导入小数之间完成的。

Luckily, we can work around this by updating MySQL conversion table: 幸运的是,我们可以通过更新MySQL转换表来解决这个问题:

from MySQLdb.constants import FIELD_TYPE
from MySQLdb.converters import conversions
import decimal

conversions[FIELD_TYPE.DECIMAL] = conversions[FIELD_TYPE.NEWDECIMAL] = decimal.Decimal

That's it; 而已; the above code resets the MySQL class and your JSON encoder type check succeeds. 上面的代码重置MySQL类,你的JSON编码器类型检查成功。

The alternative would be for you to look for the class MySQLdb is using: 替代方法是让您查找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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM