在 Python 中处理 unpickled 参数

发布于 2025-01-13 15:14:04 字数 1647 浏览 1 评论 0原文

使用Python中的多处理库,我们在场景后面pickle对象,让另一个处理它们应该保存的对象的背景。 有些对象(例如文件)是“不可腌制的”,需要特殊处理。 在下面的示例中,我使用 __getstate____setstate__ 在我的类 Person 被 pickle 时进行操作。

class Person:

    def __init__(self, name: str, age: float):
        self.name = name
        self.age = age
        self.pow_func = lambda number: number * number
        self.file = open(f'{name}_{age}_file', 'w')

    def write_to_file(self, message: str):
        self.file.write(message)

    # When this isn't implemented, pickle try to serialize class.<locals> AKA __dict__
    # If this function returns false, the function __setstate__ won't be called when unpickling
    def __getstate__(self):
        state = self.__dict__.copy()
        temp = open('temp', 'wb')
        for key, value in self.__dict__.items():
            try:
                pickle.dump(value, temp)
            except Exception:
                print(f'Cant pickle {key}, we need special treatment')
                state.update({str(key) + '_pickle_change': str(value)})
                del state[key]
        return state

    # This function responsible for the unpickling
    def __setstate__(self, state: dict):
        for key, value in state.items():
            if '_pickle_change' not in key:
                self.__dict__.update({key: value})
            else:
                print(f'Bad type: {key}, {value}')
                # What should we do here?
                pass

正如您所读到的,我将 _pickle_change 添加到每个 unpickle 对象的名称及其值的 str 中。 我的问题是,我应该在 __setstate__ 中做什么来调用文件和 lambda 函数,就像在 init 中所做的那样?我如何确保它是通用的?

Using the multiprocessing library in Python, we pickle objects behind the scene to let the other process a background of what objects they should hold.
Some objects like files are "unpickleable" and need special treatment.
In the following example, I used the __getstate__ and __setstate__ to operate when my class Person is pickled.

class Person:

    def __init__(self, name: str, age: float):
        self.name = name
        self.age = age
        self.pow_func = lambda number: number * number
        self.file = open(f'{name}_{age}_file', 'w')

    def write_to_file(self, message: str):
        self.file.write(message)

    # When this isn't implemented, pickle try to serialize class.<locals> AKA __dict__
    # If this function returns false, the function __setstate__ won't be called when unpickling
    def __getstate__(self):
        state = self.__dict__.copy()
        temp = open('temp', 'wb')
        for key, value in self.__dict__.items():
            try:
                pickle.dump(value, temp)
            except Exception:
                print(f'Cant pickle {key}, we need special treatment')
                state.update({str(key) + '_pickle_change': str(value)})
                del state[key]
        return state

    # This function responsible for the unpickling
    def __setstate__(self, state: dict):
        for key, value in state.items():
            if '_pickle_change' not in key:
                self.__dict__.update({key: value})
            else:
                print(f'Bad type: {key}, {value}')
                # What should we do here?
                pass

As you can read, I add _pickle_change to its name for every unpickle object and the str of its value.
My question is, What should I do in __setstate__to recall the file and lambda functions as I did in init? How do I make sure it will be generic?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

极度宠爱 2025-01-20 15:14:04

对于上面的示例,您可以使用 ast 将文件打开器作为字符串获取,然后在 setstate 再次对其进行评估。对于 lambda 表达式,我们可以做很多事情。您可以使用lambdaser或dill。更通用的方法是注册您自己的pickler。

更简单的方法是使用 pathos mp,它在引擎盖下使用 dill。

import dill


class Person:

    def __init__(self, name: str, age: float):
        self.name = name
        self.age = age
        self.pow_func = lambda number: number * number
        self.file = open(f'{name}_{age}_file', 'w')

    def write_to_file(self, message: str):
        self.file.write(message)
        
assert dill.dumps(Person("seimen", 42))

For the above example you could use ast to grab the file opener as string and later at setstate eval it back again. For lambdas there are plenty of thing one could to. You may use lambdser or dill. A in more generic way would be to register you own pickler.

A more simpler approach would be to use pathos mp which uses dill under the hood.

import dill


class Person:

    def __init__(self, name: str, age: float):
        self.name = name
        self.age = age
        self.pow_func = lambda number: number * number
        self.file = open(f'{name}_{age}_file', 'w')

    def write_to_file(self, message: str):
        self.file.write(message)
        
assert dill.dumps(Person("seimen", 42))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文