Невозможно поставить объект в очередь - PullRequest
0 голосов
/ 01 октября 2010

Я хочу поместить экземпляр scapy.layers.dhcp.BOOTP в multiprocessing.Queue. Каждый раз, когда я звоню put(), происходит следующее исключение:

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

Конечно, попытка выбрать экземпляр напрямую с помощью pickle.dumps() также не удалась. Но почему этот класс не является кражей?

Для всех тех, у кого не установлен scapy:

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

Есть ли другие способы "перенести" этот экземпляр в другой подпроцесс?

Ответы [ 3 ]

1 голос
/ 01 октября 2010

Ну, проблема в том, что вы не можете выбрать тип функции. Это то, что вы получаете, когда делаете type(some_user_function). Смотрите это:

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

Таким образом, такой тип функции хранится где-то на объекте, который вы пытаетесь отправить. Это не в том коде, который вы вставили, поэтому я думаю, что это в суперклассе.

Может быть, вы можете просто отправить все аргументы, необходимые для создания экземпляра scapy.layers.dhcp.BOOTP вместо экземпляра, чтобы избежать проблемы?

0 голосов
/ 19 марта 2015

Решение, которое я использую, состоит в том, чтобы поместить пакет в очередь и затем поместить его в очередь ...

0 голосов
/ 20 августа 2011

Другая вещь, которая может помочь в диагностике подобных проблем, - это использовать модуль pickle вместо cPickle (который должен использоваться неявно в queues.py)

У меня была похожая ситуация, получая полностьюбесполезное сообщение,

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

Я забрел в отладчик, нашел засоренный объект и попытался передать его в

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

и получил гораздо более полезную информацию:

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

Который намного больше указывал на проблемный код.

...