[Twisted-Python] need help for twisted FTPClient

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: ''' *def storeFile(self, path, offset=0): **(source) *<http://twistedmatrix.com/trac/browser/tags/releases/twisted-8.2.0/twisted/pr...> ** *Store a file at the given path.* *This method issues the 'STOR' FTP command. * *Returns* *A tuple of two ** Deferred*<http://twistedmatrix.com/documents/current/api/twisted.internet.defer.Deferr...> *s: * - *Deferred*<http://twistedmatrix.com/documents/current/api/twisted.internet.defer.Deferr...> * **IFinishableConsumer*<http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.I...> *. You must call the finish method on the IFinishableConsumer when the file is completely transferred. * - *Deferred*<http://twistedmatrix.com/documents/current/api/twisted.internet.defer.Deferr...> * list of control-connection responses. * ''' 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. 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() 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 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 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 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

Ioscas, I don't know much about FTP, but your code doesn't look much like the example (http://twistedmatrix.com/projects/core/documentation/examples/) . This page wasn't hard for me to find. I used "ftp twisted example" in search.yahoo.com. -George On Wed, 2009-02-11 at 11:43 +0800, 柳锴 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:
''' def storeFile(self, path, offset=0): (source)
Store a file at the given path. This method issues the 'STOR' FTP command. Returns A tuple of two Deferreds: * Deferred IFinishableConsumer. You must call the finish method on the IFinishableConsumer when the file is completely transferred. * Deferred list of control-connection responses. ''' 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.
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()
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
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
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
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
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python -- George Pauly Ring Development www.ringdevelopment.com

On Wed, 11 Feb 2009 11:43:07 +0800, 柳锴 <ioscas@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

thanks for your reply, i will check the codes.. 2009/2/11 Jean-Paul Calderone <exarkun@divmod.com>
On Wed, 11 Feb 2009 11:43:07 +0800, 柳锴 <ioscas@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
participants (3)
-
George Pauly
-
Jean-Paul Calderone
-
柳锴