2013-01-13 5 views
5

Ich verwende cPickle, um Daten zu serialisieren, die für die Protokollierung verwendet werden.cPickle - Ignoriere Zeug, das nicht serialisiert werden kann, anstatt eine Ausnahme auszulösen.

Ich möchte in der Lage sein, alles, was ich will, in ein Objekt zu werfen und es dann zu serialisieren. Normalerweise ist das in Ordnung mit cPickle, aber gerade lief auf ein Problem, wo eines der Objekte, die ich serialisieren wollte, eine Funktion enthielt. Dies führte dazu, dass cPickle eine Ausnahme ausgelöst hat.

Ich würde lieber cPickle übersprungen einfach Dinge, mit denen es nicht umgehen kann, anstatt den ganzen Prozess zu implodieren.

Was ist eine gute Möglichkeit, dies zu erreichen?

+4

Uh, fangen die erhobene Ausnahme? –

+2

Das Auffangen der Ausnahme würde nicht helfen, da das Beizen immer noch fehlschlägt, anstatt "Dinge zu überspringen, mit denen es nicht umgehen kann". – user4815162342

Antwort

2

Ich gehe davon aus, dass Sie nach einer Best-Effort-Lösung suchen, und Sie sind in Ordnung, wenn die ungefilterten Ergebnisse nicht richtig funktionieren.

Für Ihren speziellen Anwendungsfall möchten Sie möglicherweise register a pickle handler für Funktionsobjekte. Machen Sie es einfach zu einem Dummy-Handler, der gut genug für Ihre Bemühungen ist. Einen Handler für Funktionen zu erstellen ist möglich, es ist ziemlich schwierig. Um anderen Code zu vermeiden, der Pickles enthält, möchten Sie wahrscheinlich den Handler abmelden, wenn Sie den Protokollierungscode beenden.

Hier ist ein Beispiel (ohne Deregistrierung):

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)) 

Er druckt:

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

Warum nicht einfach die Ausnahme abfangen?

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

Sie können dies tun, alles andere zu halten, auch ...

>>> 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] 

gefangen Ausnahmen werden nicht erhoben.

+3

In diesem Fall wurde alles andere, was ich serialisieren wollte, nicht gespeichert. Es muss über das spezifische Feld hinausgehen, mit dem es nicht umgehen kann, und alles andere noch serialisieren. –

+0

@ChrisDutrow Siehe meine bearbeitete Antwort. :) Ich hoffe, es hilft. –

+5

@frb Dies wird immer noch fehlschlagen, wenn ein (tief geschachteltes) Attribut des Objekts, das Sie einlegen möchten, nicht gebeizt werden kann. –

0

Alternativ versuchen 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 und lebe deine Träume. Dieselben Träume lebten von DASK, IPython parallel und PySpark.

Verwandte Themen