简体   繁体   中英

AttributeError: 'module' object has no attribute '' when using pickle over sockets

I am trying to use pickle to encode instances of a class and send it across a socket and decode it at the other end, however upon reaching the other end AttributeError: 'module' object has no attribute '' is thrown when calling pickle.loads(). after googling around I confirmed that pickle is correctly importing the module containing the class definition.I cannot figure out why it is looking for a attribute that does not have a name

the function for receiving the packet

def run(self):
    while self.alive.isSet():
        try:
            cmd = self.cmd_q.get(True, 0.1)
            self.log.debug('Q Returned')
            self.handlers[cmd.type](cmd)
        except Queue.Empty as e:
            #self.log.debug('Q Returned Empty')
            pass

        if self.connected.isSet():
            self.log.debug('checking packets')
            if self.conn:
                x = select.select((self.conn,),(),(), 0.1)
                self.log.debug('SERVER returned')
            else:
                x = select.select((self.sock,),(),(), 0.1)
                self.log.debug('CLIENT returned')
            if len(x[0]) != 0:
                self.log.debug('Got Packet')
                packet = x[0][0].makefile('rwb').readline()
                self.__reply_receive(packet)

the function for sending

    def __handle_send(self, cmd):
    self.log.debug('Sending.....')
    if self.connected.isSet():
        packet = pickle.dumps(cmd.data,pickle.HIGHEST_PROTOCOL)
        if self.conn:
            self.conn.send(packet + '\n')
        else:
            self.sock.send(packet + '\n')
    self.log.debug('Sent!')

and the class definition

class Packet(object):
"""
    LINEUP      (line)
    UPDATE      (dict)
    INPUT       (line)
    DISCONN     None
    TEST        (line)
"""
LINEUP, UPDATE, INPUT, DISCONN, TEST = range(5)
def __init__(self, type, data = 'blarg'):
    self.type = type
    self.data = data

I don't think you can rely on the result of pickle.dumps to not contain any newlines. You'll need another way to find out where the pickled object ends. You might do this by sending the length first. (pickle.load can determine where the object ends, but it would have to block until the whole object can be read.)

Your use of the socket.send method is incorrect. It can send fewer bytes than you request, and it will return the number of bytes sent. You need to make a loop to send the remaining bytes, something like this:

def send_all(sock, string):
    bytes_sent = 0
    while bytes_sent < len(string):
        bytes_sent += sock.send(string[bytes_sent:])

Keep in mind that this will block until all bytes can be sent. If you don't want that, you'll have to integrate this into a select loop.

Printing a hash of your data would probably be a useful test, to figure out whether the error is in transmitting the data or in pickling/unpickling it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM