Python不会序列化未在套接字中导入的对象

时间:2016-10-07 13:55:42

标签: serialization pickle python-import python-sockets

我编写了以下简单套接字应用程序,其中对象在单独的文件中定义并且可以正常工作。

# models_object.py
class Person(object):
    def __init__(self,name,surname,age):    
        self.name = name
        self.surname = surname
        self.age = age

    def __str__(self):
        return self.name + " " + self.surname
#client.py
import cPickle,socket
from model_objects import Person

def client():     
    client = socket.socket()         
    host = socket.gethostname()           
    port = 8000                
    adem_kerenci = Person("Adem","Kerenci",22)     
    serialized_object = cPickle.dumps(adem_kerenci)
    client.connect((host, port))                   
    client.send(serialized_object)                 
    client.close()                                 

client()   
#service.py
import cPickle,socket

def server():          
    server = socket.socket()                     
    host = socket.gethostname()                  
    port = 8000                 
    server.bind((host, port))                         
    server.listen(1)                          
    connection, address = server.accept()        
    recieved_data = connection.recv(2**20)
    print cPickle.loads(recieved_data)            
    connection.close()                           

server()          

但是,如果我将Person类定义写入client.py,则代码会引发跟随错误。

Traceback (most recent call last):
  File "service.py", line 14, in <module>
     server()        
  File "service.py", line 11, in server
     print cPickle.loads(recieved_data)         
AttributeError: 'module' object has no attribute 'Person'

导入和序列化之间是否有任何关系?

注意:我们尝试过python 2.7

1 个答案:

答案 0 :(得分:1)

From documentation:

Note that functions (built-in and user-defined) are pickled by “fully qualified” name reference, not by value. This means that only the function name is pickled, along with the name of the module the function is defined in. Neither the function’s code, nor any of its function attributes are pickled. Thus the defining module must be importable in the unpickling environment, and the module must contain the named object, otherwise an exception will be raised.

This means that the object you are unpickling in the server should be importable too from the server code with the same "fully qualified" name which in the first example is: model_objects.Person. This is apparent in the first case if you try splitting the client.py and model_objects.py in one folder and service.py in another folder which will give you the same error as it is trying to import model_objects.py inside service.py but it couldn't find it.

So in the second case you can copy the class Person as well to the server code and it will work but this is bad practice or make a shared folder for both client and server which is shared production code as well (better practice).

This is because during unpickling python needs the class of the object to reinstantiate the object and use it.