2016-03-01 23 views
5

Come posso creare facilmente un oggetto che non può essere sottoposto al decapaggio per verificare i casi limite nel mio codice rpc?Crea un oggetto che non può essere sottoposto a decapaggio

ha bisogno di essere:

  1. semplice
  2. affidabile (non previsto per rompere nelle future versioni di pitone o salamoia)
  3. piattaforma Croce

Edit: la destinazione d'uso sguardi qualcosa del genere:

class TestRPCServer: 
    def foo(self): 
     return MagicalUnpicklableObject() 

def test(): 
    with run_rpc_server_and_connect_to_it() as proxy: 
     with nose.assert_raises(pickle.PickleError): 
      proxy.foo() 
+0

Cosa stai costruendo? possiamo avere un codice di esempio dell'oggetto in questione? – GLaDOS

risposta

6

Se tutto ciò di cui hai bisogno è un oggetto che genera un'eccezione quando lo metti sottoaceto, per le prove del test, puoi far esplodere lo __getstate__ method.

>>> class C: 
...  def __getstate__(self): 
...   raise Exception 
... 
>>> pickle.dumps(C()) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1374, in dumps 
    Pickler(file, protocol).dump(obj) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump 
    self.save(obj) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 723, in save_inst 
    stuff = getstate() 
    File "<stdin>", line 3, in __getstate__ 
Exception 

Difficilmente diventa più semplice di così!


Se si desidera uno scenario meno artificiale, pensare a oggetti che utilizzano le risorse del sistema operativo come handle di file, o socket, o thread, ecc

>>> with open('spam.txt', 'w') as f: 
...  pickle.dumps(f) 
... 
Traceback (most recent call last): 
    File "<stdin>", line 2, in <module> 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1374, in dumps 
    Pickler(file, protocol).dump(obj) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump 
    self.save(obj) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 306, in save 
    rv = reduce(self.proto) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy_reg.py", line 70, in _reduce_ex 
    raise TypeError, "can't pickle %s objects" % base.__name__ 
TypeError: can't pickle file objects 
+0

Il primo modo sembra essere esattamente quello di cui ho bisogno, grazie. Mi sono bloccato perché ho provato a lanciare PickleError, che in realtà non è necessario. Fare una classe di eccezioni personalizzata e lanciare è sufficiente. – cube

2

Se si desidera un elenco esplicito di oggetti che può essere messo in salamoia contro oggetti che non possono essere decapitati, sia usando pickle, che con serializzatori più avanzati come dill, questo file contiene un elenco piuttosto completo per oggetti di libreria standard. Fornisce un modo semplice per costruire ogni oggetto (in genere, un unico elemento) e mostra varianti per diverse versioni di python, se applicabile.

https://github.com/uqfoundation/dill/blob/cccbea9b715e16b742288e1e5a21a687a4d4081b/dill/_objects.py#L255

Per esempio, pickle fallirà il seguente oggetto, mentre serializzatori avanzati come dill non:

>>> import dill 
>>> dill.dumps(Ellipsis) 
b'\x80\x03cdill.dill\n_eval_repr\nq\x00X\x08\x00\x00\x00Ellipsisq\x01\x85q\x02Rq\x03.' 

serializzatori avanzati possono lavorare anche su oggetti di file e simili, btw:

>>> dill.dumps(open('foo.pkl', 'w')) 
b'\x80\x03cdill.dill\n_create_filehandle\nq\x00(X\x07\x00\x00\x00foo.pklq\x01X\x01\x00\x00\x00wq\x02K\x00\x89cdill.dill\n_get_attr\nq\x03cdill.dill\n_import_module\nq\x04X\x02\x00\x00\x00ioq\x05\x85q\x06Rq\x07X\x04\x00\x00\x00openq\x08\x86q\tRq\n\x89K\x00X\x00\x00\x00\x00q\x0btq\x0cRq\r.' 

Tuttavia, pickle e dill (E di altri serializzatori avanzate) avrà esito negativo su qualsiasi tipo che è direttamente legato ad un pitone FrameType, come un generatore:

>>> dill.dumps((i for i in [])) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Users/mmckerns/lib/python3.4/site-packages/dill-0.2.6.dev0-py3.4.egg/dill/dill.py", line 243, in dumps 
    dump(obj, file, protocol, byref, fmode, recurse)#, strictio) 
    File "/Users/mmckerns/lib/python3.4/site-packages/dill-0.2.6.dev0-py3.4.egg/dill/dill.py", line 236, in dump 
    pik.dump(obj) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/pickle.py", line 412, in dump 
    self.save(obj) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/pickle.py", line 499, in save 
    rv = reduce(self.proto) 
TypeError: can't pickle generator objects 
Problemi correlati