Getting error "cannot marshal None" in spite of adding allow_none=True while using XMLRPC in Python
Question: I've tried to create a simple download and upload system using XMLRPC in
Python

Here is the code for client (name this file as client.py)

    
    
    import sys
    import xmlrpclib
    import os
    
    def return_pause():
        """Used for creating a pause during input"""
    
        raw_input("\n\tPress enter to continue")
    
    def mod_file_download(file_name, local_port, remote_proxy, local_proxy):
        """Sending details to remote node which will send file to local node"""
    
        #print "till here"
    
        #print "{%s}\t{%s}" % (file_name,local_proxy)
    
        remote_proxy.mod_file_transfer(file_name, local_proxy)
    
    def mod_file_upload(file_path, file_name, remote_proxy):
        """Used for sending files to a receiver. Sent file will always have the name file_1.txt"""
    
        new_file_name = "file_1.txt"
        with open(file_path, "rb") as handle:
            bin_data = xmlrpclib.Binary(handle.read())
    
        remote_proxy.mod_file_receive(bin_data, new_file_name)
    
        return True
    
    ##MAIN MODULE STARTS HERE##
    
    # Connection details of remote node
    local_port = sys.argv[1]
    
    # Getting details of remote node
    remote_port = raw_input("\n\tEnter remote port ID : ")
    
    # Creating connection details of remote node
    remote_proxy = xmlrpclib.ServerProxy("http://localhost:" + remote_port + "/")
    
    # Creating connection details of local node
    local_proxy = xmlrpclib.ServerProxy("http://localhost:" + local_port + "/")
    
    while True:
        os.system('clear')
    
        print "\t. : Collab Menu for %s : .\n" % local_port
        print "\tSearch & download ...[1]"
        print "\tUpload            ...[2]"
        print "\tExit              ...[0]"
    
        input_val = raw_input("\n\n\tEnter option : ")
    
        if input_val == "1":
            file_name = raw_input("\n\tEnter name of file to be downloaded : ")
    
            mod_file_download(file_name, local_port, remote_proxy, local_proxy)
    
            return_pause()
    
        elif input_val == "2":
            file_name = raw_input("\n\tEnter name of file to be uploaded : ")
    
            file_path = "./" + file_name
    
            mod_file_upload(file_path, file_name, remote_proxy, local_proxy)
    
            return_pause()
    
        elif input_val == "0":
            print "\tExiting"
            break
    
        else:
            print "\tIncorrect option value"
            print "\tTry again..."
            return_pause()
    
    os.system('clear')
    

And here is the code for the listener (name this file as listener.py)

    
    
    import sys
    import xmlrpclib
    from SimpleXMLRPCServer import SimpleXMLRPCServer
    
    def mod_file_transfer(file_name, requestor_proxy):
        """Initiating the file transfer"""
    
        print "[mod_file_transfer fired]"
    
        file_path = "./" + file_name
    
        print requestor_proxy
    
        with open(file_path, "rb") as handle:
            bin_data = xmlrpclib.Binary(handle.read())
    
        # Connecting to requestor's server
        requestor_proxy.mod_file_download_receive(bin_data, file_name)
    
        return True
    
    def mod_file_receive(bin_data, file_name):
        """Used to receive a file upon a request of an upload"""
    
        print "[mod_file_receive fired]"
    
        new_file_name = "./" + file_name
        with open(new_file_name, "wb") as handle:
            handle.write(bin_data.data)
            return True
    
    def mod_file_download_receive(bin_data, file_name):
        """Used to receive a file upon request of a download"""
    
        print "[mod_file_download_receive fired]"
    
        new_file_name = "./" + file_name + str(1)
        with open(new_file_name, "wb") as handle:
            handle.write(bin_data.data)
            return True
    
    ##MAIN MODULE STARTS HERE##
    
    local_port = sys.argv[1]
    
    # Declared an XMLRPC server
    node = SimpleXMLRPCServer(("localhost", int(local_port)), logRequests=True, allow_none=True)
    print "Listening on port %s..." % local_port
    
    # Registered a list of functions
    node.register_function(mod_file_transfer, 'mod_file_transfer')
    node.register_function(mod_file_receive, 'mod_file_receive')
    node.register_function(mod_file_download_receive, 'mod_file_download_receive')
    
    # Initialized the XMLRPC server
    node.serve_forever()
    

**How to start the system?**

  1. Place both the files in the same directory
  2. Execute the following commands
  3. python listener 9000
  4. python listener 9500
  5. python client 9000 (then give remote client port as 9500 as input)
  6. python client 9500 (then give remote client port as 9000 as input)

File upload is working fine

_But file downloading is not working_

It's giving me the following error

    
    
    Traceback (most recent call last):
      File "collab_client.py", line 57, in <module>
        mod_file_download(file_name, local_port, remote_proxy, local_proxy)
      File "collab_client.py", line 17, in mod_file_download
        remote_proxy.mod_file_transfer(file_name, local_proxy)
      File "/usr/lib/python2.7/xmlrpclib.py", line 1240, in __call__
        return self.__send(self.__name, args)
      File "/usr/lib/python2.7/xmlrpclib.py", line 1593, in __request
        allow_none=self.__allow_none)
      File "/usr/lib/python2.7/xmlrpclib.py", line 1091, in dumps
        data = m.dumps(params)
      File "/usr/lib/python2.7/xmlrpclib.py", line 638, in dumps
        dump(v, write)
      File "/usr/lib/python2.7/xmlrpclib.py", line 660, in __dump
        f(self, value, write)
      File "/usr/lib/python2.7/xmlrpclib.py", line 762, in dump_instance
        self.dump_struct(value.__dict__, write)
      File "/usr/lib/python2.7/xmlrpclib.py", line 741, in dump_struct
        dump(v, write)
      File "/usr/lib/python2.7/xmlrpclib.py", line 660, in __dump
        f(self, value, write)
      File "/usr/lib/python2.7/xmlrpclib.py", line 762, in dump_instance
        self.dump_struct(value.__dict__, write)
      File "/usr/lib/python2.7/xmlrpclib.py", line 741, in dump_struct
        dump(v, write)
      File "/usr/lib/python2.7/xmlrpclib.py", line 660, in __dump
        f(self, value, write)
      File "/usr/lib/python2.7/xmlrpclib.py", line 720, in dump_array
        dump(v, write)
      File "/usr/lib/python2.7/xmlrpclib.py", line 660, in __dump
        f(self, value, write)
      File "/usr/lib/python2.7/xmlrpclib.py", line 664, in dump_nil
        raise TypeError, "cannot marshal None unless allow_none is enabled"
    TypeError: cannot marshal None unless allow_none is enabled
    

**But I already gave the option`allow_none=True` in the listener file.**

**Where am I going wrong?**


Answer: I found it after much headache. It seems that **connection details cannot be
sent or marshall'ed**. In the function `mod_file_transfer` I tried to send the
client connection details as an object (so that server knows to whom it has to
send the file), which was causing the error.

I simply sent the client connection details as a string and it worked. Thanks
to me!

