Python del 标记安全实例变量为垃圾收集

0 投票
1 回答
505 浏览
提问于 2025-04-18 08:48

我有一个敏感数据字段,我希望它在内存中的生命周期尽可能短。根据这篇文章这里,我有以下的实现:

class UserData:
    def __init__(data):
        self.user_data = data #sensitive data 

    def get_user_data(self):
        return UserData.decrypt(self.user_data)

    @staticmethod
    def decrypt(data):
        ...

根据这篇文章这里,看起来我能做的最好方法就是使用del命令,让这个字符串可以被垃圾回收器回收。我有以下的实现:

class UserData:
    def __init__(data):
        self.user_data = data #sensitive data 
        self._decrypted_user_data = None 

    @contextmanager      
    def get_user_data(self):
        self._decrypted_user_data = UserData.decrypt(self.user_data)
        yield
        del self._decrypted_user_data

    @staticmethod
    def decrypt(data):
        ...     

我有两个问题:

对实例变量使用del命令是否会让这个变量可以被垃圾回收器回收(也就是说,这个实例变量的引用计数是否变为0)。我之所以问这个,是因为我知道dict会返回属性。如果不是,有没有办法只标记这个实例准备好被垃圾回收,而不是整个对象?

这样做比把self._decrypted_user_data设为None更安全吗?

1 个回答

3

del 只是把一个对象标记为垃圾,不会立即删除它。

在Python中,字符串是不可变的。即使你用 del 删除了一个字符串,它在内存中仍然存在,只是无法再访问了。可以考虑使用另一种可以被覆盖的类型:

bytearray([source[, encoding[, errors]]])

返回一个新的字节数组。bytearray 类型是一种可变的整数序列,范围在 0 到 255 之间。它有大多数可变序列的常用方法,具体可以参考可变序列类型,同时也有大部分字节类型的方法,详情见字节和字节数组方法。

https://docs.python.org/3.1/library/functions.html#bytearray

为了存储密码,可以将其作为 bytearray 进行读写,也就是一串数字。要删除密码,可以覆盖 bytearray 中的元素,然后用 del 删除引用。即使这个对象再次出现,它也会变成一堆无意义的字符。

撰写回答