前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在Python中防止某些字段被Pickle序列化

在Python中防止某些字段被Pickle序列化

原创
作者头像
华科云商小徐
发布2024-05-16 09:01:46
850
发布2024-05-16 09:01:46

在Python中,如果你想防止某些字段被pickle序列化,可以使用__reduce__()方法来自定义pickle行为。__reduce__()方法允许你返回一个元组,其中包含要在对象被pickle时调用的函数以及传递给该函数的参数。下面就是我遇到的问题以及最终解决方案。

1、问题背景

在使用 Python 的 Pickle 模块对对象进行序列化时,我们有时希望排除某些字段,以防止其被序列化。这可能是由于这些字段包含敏感信息,或者只是因为它们是临时变量,不应被持久化。

2、解决方案

有几种方法可以防止某些字段被 Pickle 序列化。

  1. 使用 __getstate____setstate__ 方法

__getstate____setstate__ 是 Python 内置的特殊方法,可以让我们自定义对象的序列化和反序列化行为。我们可以通过重写这些方法来控制哪些字段被序列化。

代码语言:javascript
复制
class Something(object):
    def __init__(self):
        self._thing_id = 0
        self._cached_thing = None
​
    def __getstate__(self):
        # 只序列化 `_thing_id` 字段
        return {'_thing_id': self._thing_id}
​
    def __setstate__(self, state):
        # 从 `state` 中恢复 `_thing_id` 字段
        self._thing_id = state['_thing_id']
  1. 使用 __getnewargs____getnewargs_ex__ 方法

__getnewargs____getnewargs_ex__ 是 Python 内置的特殊方法,可以让我们在序列化对象时传递自定义参数。我们可以通过重写这些方法来控制哪些字段被序列化。

代码语言:javascript
复制
class Something(object):
    def __init__(self, thing_id):
        self._thing_id = thing_id
        self._cached_thing = None
​
    def __getnewargs__(self):
        # 只传递 `_thing_id` 参数
        return (self._thing_id,)
​
    def __getnewargs_ex__(self):
        # 只传递 `_thing_id` 参数
        return (self._thing_id,), {}
  1. 使用 __reduce__ 方法

__reduce__ 是 Python 内置的特殊方法,可以让我们自定义对象的序列化行为。我们可以通过重写这个方法来控制哪些字段被序列化。

代码语言:javascript
复制
class Something(object):
    def __init__(self, thing_id):
        self._thing_id = thing_id
        self._cached_thing = None
​
    def __reduce__(self):
        # 只返回 `_thing_id` 参数
        return (self.__class__, (self._thing_id,), {})
  1. 使用 _blacklist 变量

我们可以使用 _blacklist 变量来指定哪些字段不应被序列化。在 __getstate__ 方法中,我们可以使用这个变量来过滤掉不需要序列化的字段。

代码语言:javascript
复制
class Something(object):
    def __init__(self, thing_id):
        self._thing_id = thing_id
        self._cached_thing = None
​
    # 黑名单
    _blacklist = ['_cached_thing']
​
    def __getstate__(self):
        # 只序列化除 `_blacklist` 中的字段以外的所有字段
        return {k: v for k, v in self.__dict__.items() if k not in self._blacklist}
  1. 使用命名约定

为了避免在每个类中都指定 _blacklist 变量,我们可以使用命名约定来标记哪些字段不应被序列化。例如,我们可以将不应被序列化的字段命名为 _cached_xxx。这样,我们在 __getstate__ 方法中就可以直接过滤掉所有以 _cached_xxx 开头的字段。

代码语言:javascript
复制
class Something(object):
    def __init__(self, thing_id):
        self._thing_id = thing_id
        self._cached_thing = None
​
    def __getstate__(self):
        # 只序列化除了以下列 "_cached_" 开头的字段之外的所有字段
        return {k: v for k, v in self.__dict__.items() if not k.startswith('_cached_')}

在这个示例中,MyClass类有两个字段:sensitive_datanon_sensitive_data。我们通过定义__reduce__()方法来指定pickle时应该调用的函数。在这个函数中,我们只传递了non_sensitive_data字段,而忽略了self.sensitive_data字段,从而防止了敏感数据被pickle序列化。

我们可以根据实际需求自定义__reduce__()方法来选择哪些字段需要被pickle序列化,哪些字段不需要。

如果有任何问题可以留言讨论交流。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档