Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Cannot exclude members to pickle in metaclass

Abierto
#482 2 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Estancado
Stack tecnológico
python
Área
tooling

Línea de trabajo

Empieza reproduciendo el fallo en el ejemplo proporcionado de SingletonMeta, centrándote en test_singleton_pickle y en la llamada final a cloudpickle.dumps(test_singleton). Lee cómo cloudpickle gestiona las metaclases y los métodos getstate, y verifica después que las instancias se puedan volcar y cargar sin intentar serializar el RLock de la metaclase, manteniendo las assertions mostradas.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

pickle issue

In the example below, I implemented __getstate__(cls) that returns empty dict
in order not to pickle cls.INSTANCES and cls.LOCK members of metaclass SingletonMeta.

But it seems that cloudpickle still tries to pickle those members
and fails to pickle since threading.RLock is not picklable.

import cloudpickle

from threading import RLock


class SingletonMeta(type):
    def __new__(cls, name, bases, namespace):
        return super().__new__(cls, name, bases, namespace)

    def __init__(cls, name, bases, namespace):
        super().__init__(name, bases, namespace)
        cls.INSTANCES = {}
        cls.LOCK = RLock()

    def __call__(cls, *args, **kwargs):
        key = cls.__getkey__(*args, **kwargs)
        key = tuple(key.items())
        if key not in cls.INSTANCES:
            with cls.LOCK:
                if key not in cls.INSTANCES:
                    cls.INSTANCES[key] = super().__call__(*args, **kwargs)
        instance = cls.INSTANCES[key]
        return instance

    def __getstate__(cls):
        # don't want to pickle cls.INSTANCES and cls.LOCK
        return {}

    def __setstate__(cls, state):
        pass


class SingletonClass(metaclass=SingletonMeta):
    def __init__(self, key):
        self.key = key
        self.transient = [self.key]

    def __getstate__(self):
        state = self.__dict__.copy()
        del state["transient"]
        return state

    def __setstate__(self, state):
        for name, value in state.items():
            setattr(self, name, value)
        self.transient = [self.key]

    @classmethod
    def __getkey__(cls, key):
        return {"key": key}


# singleton implementation works fine as long as metaclass = SingletonMeta
def test_singleton():
    singleton_instance1 = SingletonClass(0)
    singleton_instance2 = SingletonClass(0)
    singleton_instance3 = SingletonClass(1)
    assert singleton_instance1 is singleton_instance2
    assert singleton_instance1 is not singleton_instance3


# pickling instances works fine if metaclass != SingletonMeta
# but raises `TypeError: cannot pickle '_thread.RLock' object` if metaclass = SingletonMeta
def test_singleton_pickle():
    singleton_instance1 = SingletonClass(0)
    singleton_instance1_loaded = cloudpickle.loads(
        cloudpickle.dumps(singleton_instance1)
    )
    assert singleton_instance1 is not singleton_instance1_loaded
    assert singleton_instance1.key == singleton_instance1_loaded.key
    assert singleton_instance1.transient == singleton_instance1_loaded.transient


if __name__ == "__main__":
    # singleton implementation works fine as long as metaclass = SingletonMeta
    test_singleton()

    # pickling instances works fine if metaclass != SingletonMeta
    # but raises `TypeError: cannot pickle '_thread.RLock' object` if metaclass = SingletonMeta
    test_singleton_pickle()

    # raises "TypeError: cannot pickle '_thread.RLock' object"
    cloudpickle.dumps(test_singleton)
Lenguaje dominante
Python
Estrellas
1.9k
Forks
198
Merge medio
1 d 10 h
PR fusionados (30 d)
1

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de cloudpipe/cloudpickle

Todos los issues de cloudpipe/cloudpickle

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.