Descomprimiendo python2 datetime bajo python3

Elegí usar pickle (+ base64 + sockets TCP) para comunicar datos entre mi código de python3 y el código de python2 heredado, pero tengo problemas con los objetos de datetime y datetime :

El objeto PY3 se desintegra bien en PY2, pero a la inversa genera un TypeError al llamar al constructor de fecha y hora, y luego a UnicodeEncodeError en la función load_reduce.

Un progtwig de prueba corto y el registro, que incluye la salida de disección de los pepinillos PY2 y PY3, están disponibles en este resumen.

¿Es este un error de datetime y datetime ? ¿Es posible que las datetime.__getstate__/__setstate__ no sean compatibles?

Cualquier comentario sobre el código es bienvenido …

Complemento

Pepinillo PY-3.4.0:

  0: \x80 PROTO 2 2: c GLOBAL 'datetime datetime' 21: q BINPUT 0 23: c GLOBAL '_codecs encode' 39: q BINPUT 1 41: X BINUNICODE u'\x07\xde\x07\x11\x0f\x06\x11\x05\n\x90' 58: q BINPUT 2 60: X BINUNICODE u'latin1' 71: q BINPUT 3 73: \x86 TUPLE2 74: q BINPUT 4 76: R REDUCE 77: q BINPUT 5 79: \x85 TUPLE1 80: q BINPUT 6 82: R REDUCE 83: q BINPUT 7 85: . STOP 

Pepinillo PY-2.7.6:

  0: \\x80 PROTO 2 2: c GLOBAL 'datetime datetime' 21: q BINPUT 0 23: U SHORT_BINSTRING '\\x07\xc3\x9e\\x07\\x11\\x0f\\x06\\x11\\x05\\n\\x90' 35: q BINPUT 1 37: \\x85 TUPLE1 38: q BINPUT 2 40: R REDUCE 41: q BINPUT 3 43: ] EMPTY_LIST 44: q BINPUT 4 46: N NONE 47: \\x87 TUPLE3 48: q BINPUT 5 50: . STOP 

PY-3.4.0 pickle.load_reduce :

 def load_reduce(self): stack = self.stack args = stack.pop() func = stack[-1] try: value = func(*args) except: print(sys.exc_info()) print(func, args) raise stack[-1] = value dispatch[REDUCE[0]] = load_reduce 

PY-3.4.0 datetime soporte de pickle:

 # Pickle support. def _getstate(self): yhi, ylo = divmod(self._year, 256) us2, us3 = divmod(self._microsecond, 256) us1, us2 = divmod(us2, 256) basestate = bytes([yhi, ylo, self._month, self._day, self._hour, self._minute, self._second, us1, us2, us3]) if self._tzinfo is None: return (basestate,) else: return (basestate, self._tzinfo) def __setstate(self, string, tzinfo): (yhi, ylo, self._month, self._day, self._hour, self._minute, self._second, us1, us2, us3) = string self._year = yhi * 256 + ylo self._microsecond = (((us1 << 8) | us2) << 8) | us3 if tzinfo is None or isinstance(tzinfo, _tzinfo_class): self._tzinfo = tzinfo else: raise TypeError("bad tzinfo state arg %r" % tzinfo) def __reduce__(self): return (self.__class__, self._getstate()) 

La solución es usar la encoding="bytes" siguiente manera:

 pickled_bytes = bytes(pickled_str, encoding='latin1') # If your input is a string(not my case) data = pickle.loads(pickled_bytes, encoding='bytes') 

(Gracias a Tim Peters por la sugerencia)

El problema aún está abierto en http://bugs.python.org/issue22005 en cuanto a por qué se requiere esto.