On Wed, 11 Feb 2009 11:43:07 +0800, 柳锴 <ios...@gmail.com> wrote:
hello, everyone:

   I'm new to twisted and ftp protocol. for some purpose, i need a python
ftp client to do list, get, put, remove operations upon a FTP server which
is implemented with twisted.
   here is my codes, testing for 'get' passed, but 'put' failed. i checked
the api of storeFile, abd got these:

[snip]

but i don't know how to handle it, :)
sorry for the rubbish codes, but i really need help from you guys, it's
hard to find some useful info from twisted official doc,
Any suggestion on how to write a nice ftp client with twisted is welcome.
Thanks in advance.

The most obvious problem with the code is that it uses reactor.run and
reactor.stop too much.  You can start and stop the reactor exactly once.

IOSCAS

______________________________________________________________________________

from twisted.protocols.ftp import FTPClient, FTPFileListProtocol
from twisted.internet.protocol import Protocol, ClientCreator
from twisted.python import usage
from twisted.internet import reactor, defer

class SaveFile(Protocol):
   '''
   save the ftp file to local filesystem
   '''
   def __init__(self, output):
       self.fout = open(output, 'w')

   def dataReceived(self, data):
       self.fout.write(data)
       self.fout.close()

This is also probably wrong.  dataReceived may be called multiple times.
You can't close the output file until you've received all the data.  I'm
not sure, but connectionLost is probably called when all data has been
received (or if there is an error receiving the data).

class FTP:
   '''
   a simple ftp client
   '''
   def __init__(self, host, port):
       '''
       init
       '''
       self.__host = host
       self.__port = port
       self.__username = 'aaa'
       self.__passwd = 'bbb'
       self.__passive = 1

   def __get(self, ftp_client, src, des):
       '''
       '''
       save_file = SaveFile(des)
       d = ftp_client.retrieveFile(src, save_file)
       d = ftp_client.quit()
       d.addCallback(lambda result: reactor.stop())
       return d

Don't stop the reactor here.  Stopping the reactor means your program is
basically done and you don't want to do anything else with Twisted.

   def get(self, src, des):
       '''
       get src file from ftp server, store it in des
       '''
       creator = ClientCreator(reactor, FTPClient, self.__username,
self.__passwd, self.__passive)
       defer = creator.connectTCP(self.__host,
self.__port).addCallback(self.__get, src, des)
       reactor.run()
       return defer.result

Don't start the reactor here.  Start the reactor in the "main" part of your
program.  Also, don't access "defer.result".  Instead, just return "defer".


   def __put(self, ftp_client, src, des):
       '''
       '''
       source_file = os.path.basename(src)
       target_dir = os.path.dirname(des)
       ftp_client.changeDirectory(target_dir)
       d = ftp_client.storeFile(src)
       d = ftp_client.quit()
       d.addCallback(lambda result: reactor.stop())
       return d

Again, don't use stop here.

  def put(self, src, des):
       '''
       put src file to ftp server, store it in des
       '''
       creator = ClientCreator(reactor, FTPClient, self.__username,
self.__passwd, self.__passive)
       defer = creator.connectTCP(self.__host,
self.__port).addCallback(self.__put, src, des)
       reactor.run()
       return defer.result


And don't use run or .result here.

Jean-Paul

_______________________________________________
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

Reply via email to