Google app engine 子类化db.TextProperty以将python dict存储为JSON并将默认编码设置为除ASCII以外的任何内容
使用GoogleAppEngine(python SDK),我创建了一个自定义JSONProperty(),作为db.TextProperty()的子类。我的目标是将python dict动态存储为JSON并轻松检索。我遵循了通过Google找到的各种示例,设置自定义属性类和方法非常简单 但是,我的一些dict值(字符串)是用utf-8编码的。将模型保存到数据存储中时,我遇到了一个可怕的Unicode错误(对于数据存储文本属性,默认编码为ASCII)。子类化db.BlobProperty无法解决此问题 基本上,我的代码执行以下操作:将资源实体存储到数据存储中(URL作为StringProperty,POST/GET有效负载作为JSONProperty存储在dict中),稍后获取它们(不包括代码)。我选择不使用pickle来存储有效负载,因为我是一个JSON怪胎,无法存储对象 自定义JSONProperty:Google app engine 子类化db.TextProperty以将python dict存储为JSON并将默认编码设置为除ASCII以外的任何内容,google-app-engine,unicode,utf-8,google-cloud-datastore,Google App Engine,Unicode,Utf 8,Google Cloud Datastore,使用GoogleAppEngine(python SDK),我创建了一个自定义JSONProperty(),作为db.TextProperty()的子类。我的目标是将python dict动态存储为JSON并轻松检索。我遵循了通过Google找到的各种示例,设置自定义属性类和方法非常简单 但是,我的一些dict值(字符串)是用utf-8编码的。将模型保存到数据存储中时,我遇到了一个可怕的Unicode错误(对于数据存储文本属性,默认编码为ASCII)。子类化db.BlobProperty无法解决
class JSONProperty(db.TextProperty):
def get_value_for_datastore(self, model_instance):
value = super(JSONProperty, self).get_value_for_datastore(model_instance)
return json.dumps(value)
def make_value_from_datastore(self, value):
if value is None:
return {}
if isinstance(value, basestring):
return json.loads(value)
return value
将模型放入数据存储:
res = Resource()
res.init_payloads()
res.url = "http://www.somesite.com/someform/"
res.param = { 'name': "SomeField", 'default': u"éàôfoobarç" }
res.put()
这将抛出与ASCII编码相关的UnicodeDecodeError。也许值得注意的是,我只在生产服务器上(每次)收到这个错误。我在dev上使用python2.5.2
回溯(最近一次呼叫最后一次):
文件“/base/data/home/apps/delpythian/1.350065314722833389/core/handlers/ResetHandler.py”,第68行,在
return resu one.put()
文件“/base/python\u runtime/python\u lib/versions/1/google/appengine/ext/db/init.py”,第984行,输入
返回datastore.Put(self.\u实体,config=config)
文件“/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py”,第455行,输入
return\u GetConnection().async\u put(配置、实体、额外的\u钩子)。get\u result()
文件“/base/python_runtime/python_lib/versions/1/google/appengine/datastore/datastore_rpc.py”,第1219行,异步输入
对于pbsgen中的pbs:
文件“/base/python\u runtime/python\u lib/versions/1/google/appengine/datastore/datastore\u rpc.py”,第1070行,位于生成pb列表中
pb=值_至_pb(值)
文件“/base/python_runtime/python_lib/versions/1/google/appengine/api/datastore.py”,第239行,在实体_到_pb中
返回实体。_ToPb()
文件“/base/python\u runtime/python\u lib/versions/1/google/appengine/api/datastore.py”,第841行,在
属性=数据存储\类型.ToPropertyPb(名称、值)
ToPropertyPb中的文件“/base/python\u runtime/python\u lib/versions/1/google/appengine/api/datastore\u types.py”,第1672行
pbvalue=pack_prop(name,v,pb.mutable_value())
PackString中的文件“/base/python\u runtime/python\u lib/versions/1/google/appengine/api/datastore\u types.py”,第1485行
pbvalue.set_stringvalue(unicode(value).encode('utf-8'))
UnicodeDecodeError:“ascii”编解码器无法解码位置32中的字节0xc3:序号不在范围内(128)
我的问题是:有没有一种方法可以将db.TextProperty()类划分为子类并设置/实施自定义编码?还是我做错了什么?我尽量避免使用str(),并遵循“早解码,处处使用Unicode,晚编码”的规则
更新:添加了代码和stacktrace。下面是一个将unicode字符串从字典移动到序列化JSON字符串再移动到TextProperty的最小示例:
class Thing(db.Model):
json = db.TextProperty()
class MainHandler(webapp.RequestHandler):
def get(self):
data = {'word': u"r\xe9sum\xe9"}
json = simplejson.dumps(data, ensure_ascii=False)
Thing(json=json).put()
这对我在开发和生产中都很有用。看看这行:
PackString pbvalue.set_stringvalue(unicode(value).encode('utf-8'))UnicodeDecodeError:'ascii'
似乎appengine希望所有字符串值都是unicode。调用unicode(值)没有指定编码,因此可能默认为ascii,除非值已经是unicode,例如:
>>> u = u"ąęćźż"
>>> s = u.encode('utf-8')
>>> unicode(u) # fine
>>> unicode(s, 'utf-8') # fine
>>> unicode(s) # blows up (try's ascii) (on my interpreter)
json.dumps将编码一个utf-8字符串(默认情况下),这就是unicode无法处理它的原因
试试这个:
>>> return unicode(json.dumps(...), 'utf-8')
你应该没事的
至于为什么阿彭金爆炸了,而你的翻译还好,我猜可能是当地人
设置,docstring for unicode表示默认为当前默认编码,您的默认编码为utf-8,gae的默认编码为ascii。请添加代码示例和堆栈跟踪。特别是,我想确认UnicodeError是在您尝试存储TextProperty时发生的,而不是在您尝试将Python字典序列化为JSON时发生的。更新了问题,添加了代码和堆栈跟踪。您好,谢谢,我没有考虑查看dumps()方法。然而,我仍然在prod上获得相同的堆栈跟踪。在dev上运行良好。这令人困惑!