2010-10-01 23 views
0

Je souhaite placer une instance de scapy.layers.dhcp.BOOTP sur un multiprocessing.Queue. Chaque fois que j'appelle put() l'exception suivante a lieu:Impossible de mettre l'objet sur la file d'attente

Traceback (most recent call last): 
    File "/usr/lib/python2.6/multiprocessing/queues.py", line 242, in _feed 
    send(obj) 
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed 

de la cause en essayant de décaper l'instance en utilisant directement pickle.dumps() échoue également. Mais pourquoi cette classe n'est pas picklable?

Pour tous ceux qui n'ont pas scapy installé:

class BOOTP(Packet): 
    name = "BOOTP" 
    fields_desc = [ ByteEnumField("op",1, {1:"BOOTREQUEST", 2:"BOOTREPLY"}), 
        ByteField("htype",1), 
        ByteField("hlen",6), 
        ByteField("hops",0), 
        IntField("xid",0), 
        ShortField("secs",0), 
        FlagsField("flags", 0, 16, "???????????????B"), 
        IPField("ciaddr","0.0.0.0"), 
        IPField("yiaddr","0.0.0.0"), 
        IPField("siaddr","0.0.0.0"), 
        IPField("giaddr","0.0.0.0"), 
        Field("chaddr","", "16s"), 
        Field("sname","","64s"), 
        Field("file","","128s"), 
        StrField("options","") ] 
    def guess_payload_class(self, payload): 
     if self.options[:len(dhcpmagic)] == dhcpmagic: 
      return DHCP 
     else: 
      return Packet.guess_payload_class(self, payload) 
    def extract_padding(self,s): 
     if self.options[:len(dhcpmagic)] == dhcpmagic: 
      # set BOOTP options to DHCP magic cookie and make rest a payload of DHCP options 
      payload = self.options[len(dhcpmagic):] 
      self.options = self.options[:len(dhcpmagic)] 
      return payload, None 
     else: 
      return "", None 
    def hashret(self): 
     return struct.pack("L", self.xid) 
    def answers(self, other): 
     if not isinstance(other, BOOTP): 
      return 0 
     return self.xid == other.xid 

Y at-il d'autres moyens de « transport » cette instance à l'autre sous-processus?

Répondre

1

Eh bien, le problème est que vous ne pouvez pas choisir le type de fonction. C'est ce que vous obtenez quand vous faites type(some_user_function). Voir ceci:

>>> import types 
>>> pickle.dumps(types.FunctionType) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'picke' is not defined 
>>> pickle.dumps(types.FunctionType) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "C:\Python26\lib\pickle.py", line 1366, in dumps 
    Pickler(file, protocol).dump(obj) 
    File "C:\Python26\lib\pickle.py", line 224, in dump 
    self.save(obj) 
    File "C:\Python26\lib\pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "C:\Python26\lib\pickle.py", line 748, in save_global 
    (obj, module, name)) 
pickle.PicklingError: Can't pickle <type 'function'>: it's not found as __built 
n__.function 

Donc un tel type de fonction est stocké quelque part sur l'objet que vous essayez d'envoyer. Ce n'est pas dans le code que vous avez collé, donc je suppose que c'est sur la superclasse.

Peut-être que vous pouvez simplement envoyer tous les arguments nécessaires pour créer une instance de scapy.layers.dhcp.BOOTP au lieu de l'instance pour éviter le problème?

+0

J'ai copié tous les attributs pertinents à un nouveau, créé propres objets, comme je ne l'ai pas trouvé une autre solution. –

0

L'autre chose qui peut aider à diagnostiquer les problèmes comme ceux-ci est d'utiliser le module pickle au lieu de cPickle (qui doit être utilisé implicitement par se queues.py)

J'ai eu une situation similaire, obtenir un complètement inutile message,

Can't pickle <type 'function'>: attribute lookup __builtin__.function failed 

je me promenais dans le débogueur, trouvé l'objet décapé, et avons essayé de le transmettre à

pickle.dump(myobj,open('outfile','w'),-1) 

et eu un beaucoup plus utile:

PicklingError: Can't pickle <function findAllRefs at 0x105809f50>: 
    it's not found as buildsys.repoclient.findAllRefs 

Qui a souligné beaucoup plus directement au code problématique.

0

Une solution que j'utilise est str le paquet, puis le mettre sur la file d'attente ...