我可以在谷歌的BigTable数据存储中保存一个Python字典而不显式序列化吗?

1 投票
3 回答
1538 浏览
提问于 2025-04-15 17:19

我有一个Python字典,想把它存储在谷歌的BigTable数据库里(它是一个db.Model类中的一个属性)。

有没有简单的方法可以做到这一点?比如使用db.DictionaryProperty?还是说我必须用pickle来把我的字典转换成可以存储的格式?我的字典结构比较简单,键是字符串,但有些键可能还会包含子字典。例如:

{ 
    'myKey' : 100,
    'another' : 'aha',
    'a sub dictionary' : { 'a': 1, 'b':2 }
}

另外,如果可以的话,我希望以二进制格式来存储,而不是文本格式。

3 个回答

1

我想你是说,当你需要访问字典的时候,是一次性获取所有内容吗?也就是说,你不需要在数据存储中逐个取值?

如果是这样的话,你需要把数据进行序列化,不过不一定要用pickle;我们用的是simplejson。然后取数据的时候,只需要重写toBasicType()方法,像这样:

class MyModel(db.Model):
# 定义一些属性,包括“data”,这是一个包含较大字典的TextProperty
def toBasicType(self):
return {'metadata': self.getMetadata(),
'data': simplejson.loads(self.data)}

创建的时候需要调用MyModel(..., simplejson.dumps(data), ...)。

如果你已经在使用pickle,那可能是个不错的选择,但对我们来说,simplejson的效果很好。

1

我觉得你无法避免对你的对象进行序列化。

我会定义一个模型来存储每一对键和值:

class DictModel(db.Model):
    value = db.TextProperty()

要保存到数据存储中,我会使用:

def set_value(key, value):
    key = DictModel(value=pickle.dumps(value), key_name=key)
    key.save()
    return key

然后要获取数据:

def get_value(key):
    return pickle.loads(DictModel.get_by_key_name(key).value)
8

这里有另一种方法:

class DictProperty(db.Property):
  data_type = dict

  def get_value_for_datastore(self, model_instance):
    value = super(DictProperty, self).get_value_for_datastore(model_instance)
    return db.Blob(pickle.dumps(value))

  def make_value_from_datastore(self, value):
    if value is None:
      return dict()
    return pickle.loads(value)

  def default_value(self):
    if self.default is None:
      return dict()
    else:
      return super(DictProperty, self).default_value().copy()

  def validate(self, value):
    if not isinstance(value, dict):
      raise db.BadValueError('Property %s needs to be convertible '
                             'to a dict instance (%s) of class dict' % (self.name, value))
    return super(DictProperty, self).validate(value)

  def empty(self, value):
    return value is None

撰写回答