2013-01-13 13 views
5

Używam cPickle do serializowania danych używanych do rejestrowania.cZamknij - zignoruj ​​elementy, których nie może serializować, zamiast zgłaszać wyjątek.

Chciałbym móc rzucić, co chcę, do obiektu, a następnie serializować go. Zwykle jest to w porządku z cPickle, ale właśnie wpadł na problem, w którym jeden z obiektów, które chciałem serializować, zawierał funkcję. To spowodowało, że cPickle podniósł wyjątek.

Wolałbym cPickle tylko przeskoczyć rzeczy, z którymi nie może sobie poradzić, zamiast powodować implozję całego procesu.

Jaki jest dobry sposób, aby tak się stało?

+4

Uh, złap podniesiony wyjątek? –

+2

Złapanie wyjątku nie pomogłoby, ponieważ wytrawianie nadal kończyłoby się niepowodzeniem, zamiast "pomijać rzeczy, z którymi nie może sobie poradzić". – user4815162342

Odpowiedz

2

Zakładam, że szukasz najlepszego rozwiązania i masz się dobrze, jeśli niepoprawione wyniki nie działają poprawnie.

Dla konkretnego przypadku użycia możesz chcieć register a pickle handler dla obiektów funkcji. Po prostu uczyń z niego manekina, który jest wystarczająco dobry dla twoich najlepszych starań. Wykonywanie funkcji obsługi jest możliwe, jest to raczej trudne. Aby uniknąć wpływu na inny kod pikli, prawdopodobnie zechcesz wyrejestrować program obsługi przy wychodzeniu z kodu logowania.

Oto przykład (bez wyrejestrowania):

import cPickle 
import copy_reg 
from types import FunctionType 

# data to pickle: note that o['x'] is a lambda and they 
# aren't natively picklable (at this time) 
o = {'x': lambda x: x, 'y': 1} 

# shows that o is not natively picklable (because of 
# o['x']) 
try: 
    cPickle.dumps(o) 
except TypeError: 
    print "not natively picklable" 
else: 
    print "was pickled natively" 

# create a mechanisms to turn unpickable functions int 
# stub objects (the string "STUB" in this case) 
def stub_pickler(obj): 
    return stub_unpickler,() 
def stub_unpickler(): 
    return "STUB" 
copy_reg.pickle(
    FunctionType, 
    stub_pickler, stub_unpickler) 

# shows that o is now picklable but o['x'] is restored 
# to the stub object instead of its original lambda 
print cPickle.loads(cPickle.dumps(o)) 

Drukuje:

not natively picklable 
{'y': 1, 'x': 'STUB'} 
-1

Dlaczego nie tylko uwięzić wyjątek?

try: 
    cPickle.dumps(obj) 
except cPickle.PicklingError: 
    pass 

Można to zrobić, aby zachować wszystko inne, zbyt ...

>>> def safe_pickle(L): 
...  result = [] 
...  for target in L: 
...    try: 
...      result.append(cPickle.dumps(target)) 
...    except (cPickle.PicklingError, TypeError): 
...      result.append(None) 
...  return result 
... 
>>> safe_pickle(["A",open('file.txt')]) 
["S'A'\n.", None] 

Caught wyjątki nie są podnoszone.

+3

W takim przypadku wszystko, co chciałem serializować, nie zostało zapisane. Musi przeskakiwać nad konkretnym polem, z którym nie może sobie poradzić i nadal serializować wszystko inne. –

+0

@ChrisDutrow Wyświetl poprawioną odpowiedź. :) Mam nadzieję, że to pomoże. –

+5

@frb to się nie powiedzie, jeśli nie można wytrawić (głęboko zagnieżdżonego) atrybutu obiektu, który próbujesz ogłuszać. –

0

Ewentualnie spróbuj cloudpickle:

>>> import cloudpickle 
>>> squared = lambda x: x ** 2 
>>> pickled_lambda = cloudpickle.dumps(squared) 

>>> import pickle 
>>> new_squared = pickle.loads(pickled_lambda) 
>>> new_squared(2) 
4 

we can pickle that

pip install cloudpickle i żyj swoimi marzeniami. Te same sny przeżywane przez dask, IPython parallel i PySpark.

Powiązane problemy