gpt4 book ai didi

Python decimal.Decimal 不一样

转载 作者:太空宇宙 更新时间:2023-11-04 07:37:45 30 4
gpt4 key购买 nike

我在用 Python 编码为 JSON 时遇到问题,特别是 decimal.Decimal 值。我正在使用它为 Google App Engine 应用程序输出 JSON。

为了避免 Python 中默认的 json 模块告诉我它不能处理 decimal.Decimal 对象的异常,我使用了这个编码器子类:

class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return float(o)
return super(DecimalEncoder, self).default(o)

在其他应用程序上,这确实有效。在这种情况下,它没有。在经历了很多挫折之后,我发现这会产生奇怪的结果:

print id(decimal.Decimal)
print id(type(o))

人们会期望 id 是相同的,因为同一个类对象在内存中只驻留一次是有意义的。因为 id 不同,isinstance() 不起作用。

会不会是 decimal.Decimal 已经导入到其他地方,例如在 App Engine 和/或 webapp2 包中?

以下模块在我的系统(OSx 10.10、Python 2.7.6、GAE SDK 1.9.20)上重现了错误。只需创建一个 GAE 应用程序并将其放入 main.py 中:

import webapp2, decimal, json, MySQLdb, sys

class DecimalEncoder(json.JSONEncoder):
def default(self, o):
print id(decimal.Decimal)
print id(type(o))
if isinstance(o, decimal.Decimal):
return float(o)
return super(DecimalEncoder, self).default(o)

class MainHandler(webapp2.RequestHandler):
def get(self):
db = MySQLdb.connect(unix_socket='/var/mysql/mysql.sock', host='localhost', user='root', db='ssss', charset='utf8')
cursor = db.cursor(MySQLdb.cursors.DictCursor)
cursor.execute("SELECT id, price FROM product WHERE id = 1")
record = cursor.fetchone()

self.response.headers['Content-Type'] = 'application/json'
self.response.write(json.dumps(
record,
cls=DecimalEncoder,
indent=4,
separators=(',', ': ')
))

app = webapp2.WSGIApplication([
('/', MainHandler)
], debug=True)

数据库表:

CREATE TABLE `product` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`price` decimal(10,2) unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
INSERT INTO product VALUES(0, 5.00);

最佳答案

看来 decimal.Decimal 类在 Google App Engine SDK 中某处打了补丁(或者重新加载了模块),这是在 MySQL 转换之间完成的库导入 decimal 和你导入相同的。

幸运的是,我们可以通过更新 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)

关于Python decimal.Decimal 不一样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30694446/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com