Python decimal.Decimal ID不一样 [英] Python decimal.Decimal id not the same
问题描述
我在使用Python对JSON进行编码时遇到问题,特别是使用decimal.Decimal值。我使用它为Google App Engine应用程序输出JSON。
为了绕过默认的 json
模块在Python中告诉我它不能处理decimal.Decimal对象,我使用这个编码器子类:
class DecimalEncoder json.JSONEncoder):
def default(self,o):
if isinstance(o,decimal.Decimal):
返回float(o)
返回超级(DecimalEncoder,self ).default(o)
在其他应用程序中,这确实起作用。在这种情况下,它不会。经过多次的挫折后,我发现这给出了奇怪的结果:
print id(decimal.Decimal)
print id类型(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))
如果isinstance(o,decimal.Decimal):
返回float(o)
返回超级(DecimalEncoder,self).default(o)
$ b $ 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(
记录,
cls = Dec imalEncoder,
indent = 4,
separators =(',',':')
))
app = webapp2.WSGIApplication([
('/',MainHandler)
],debug = True)
数据库表:
CREATE TABLE`product`(
`id` int(11)unsigned NOT NULL AUTO_INCREMENT,
` (10,2)unsigned DEFAULT NULL,
PRIMARY KEY(`id`)
)ENGINE = InnoDB AUTO_INCREMENT = 0 DEFAULT CHARSET = utf8;
插入产品VALUES(0,5.00);
看来 decimal .Decimal
类在Google App Engine SDK中的某处修补(或者模块被重新加载),这是在导入的MySQL转换库之间完成的。
幸运的是,我们可以通过更新MySQL转换表来解决这个问题:
MySQLdb.constants中的
从MySQLdb.converters导入FIELD_TYPE
导入转换
导入十进制
转换[FIELD_TYPE。 DECIMAL] = conversions [FIELD_TYPE.NEWDECIMAL] = decimal.Decimal
就是这样;上面的代码重置了MySQL类,并且您的JSON编码器类型检查成功了。
另一种方法是查找类 I am having a problem with encoding to JSON in Python, specifically with decimal.Decimal values. I am using this to output JSON for a Google App Engine application. To circumvent the exception from the default On other applications, this does work. In this case it doesn't. After much frustration I found out that this gives weird results: One would expect the id's to be identical, because it makes sense for the same class object to reside only once in memory. Because the id's differ, Could it be that decimal.Decimal is already imported somewhere else, for instance in the App Engine and/or webapp2 packages? The following modul reproduces the error on my system (OSx 10.10, Python 2.7.6, GAE SDK 1.9.20). Just create an GAE application and put this in main.py: Database table:
It appears that the Luckily, we can work around this by updating MySQL conversion table: That's it; the above code resets the MySQL class and your JSON encoder type check succeeds. The alternative would be for you to look for the class
这篇关于Python decimal.Decimal ID不一样的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! MySQLdb
正在使用:
$ $ p $ class DecimalEncoder(json.JSONEncoder):
def default(self,o ):
如果isinstance(o,MySQLdb.converters.conversions [MySQLdb.constants.FIELD_TYPE.DECIMAL]):
返回float(o)
返回超级(DecimalEncoder,self).default( o)
json
module in Python telling me that it can't handle decimal.Decimal objects, I am using this encoder subclass: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))
isinstance()
doesn't work.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
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.from MySQLdb.constants import FIELD_TYPE
from MySQLdb.converters import conversions
import decimal
conversions[FIELD_TYPE.DECIMAL] = conversions[FIELD_TYPE.NEWDECIMAL] = decimal.Decimal
MySQLdb
is using: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)