thanks for your reply, i will check the codes..<br><br><div class="gmail_quote">2009/2/11 Jean-Paul Calderone <span dir="ltr">&lt;<a href="mailto:exarkun@divmod.com">exarkun@divmod.com</a>&gt;</span><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d">On Wed, 11 Feb 2009 11:43:07 +0800, ÁøïÇ &lt;<a href="mailto:ioscas@gmail.com" target="_blank">ioscas@gmail.com</a>&gt; wrote:<br>
</div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="Ih2E3d">
hello, everyone:<br>
<br>
 &nbsp; I&#39;m new to twisted and ftp protocol. for some purpose, i need a python<br>
ftp client to do list, get, put, remove operations upon a FTP server which<br>
is implemented with twisted.<br>
 &nbsp; here is my codes, testing for &#39;get&#39; passed, but &#39;put&#39; failed. i checked<br>
the api of storeFile, abd got these:<br>
<br></div>
[snip]<div class="Ih2E3d"><br>
<br>
but i don&#39;t know how to handle it, :)<br>
sorry for the rubbish codes, but i really need help from you guys, it&#39;s<br>
hard to find some useful info from twisted official doc,<br>
Any suggestion on how to write a nice ftp client with twisted is welcome.<br>
Thanks in advance.<br>
</div></blockquote>
<br>
The most obvious problem with the code is that it uses reactor.run and<br>
reactor.stop too much. &nbsp;You can start and stop the reactor exactly once.<div class="Ih2E3d"><br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
IOSCAS<br>
<br>
______________________________________________________________________________<br>
<br>
from twisted.protocols.ftp import FTPClient, FTPFileListProtocol<br>
from twisted.internet.protocol import Protocol, ClientCreator<br>
from twisted.python import usage<br>
from twisted.internet import reactor, defer<br>
<br>
class SaveFile(Protocol):<br>
 &nbsp; &#39;&#39;&#39;<br>
 &nbsp; save the ftp file to local filesystem<br>
 &nbsp; &#39;&#39;&#39;<br>
 &nbsp; def __init__(self, output):<br>
 &nbsp; &nbsp; &nbsp; self.fout = open(output, &#39;w&#39;)<br>
<br>
 &nbsp; def dataReceived(self, data):<br>
 &nbsp; &nbsp; &nbsp; self.fout.write(data)<br>
 &nbsp; &nbsp; &nbsp; self.fout.close()<br>
</blockquote>
<br></div>
This is also probably wrong. &nbsp;dataReceived may be called multiple times.<br>
You can&#39;t close the output file until you&#39;ve received all the data. &nbsp;I&#39;m<br>
not sure, but connectionLost is probably called when all data has been<br>
received (or if there is an error receiving the data).<div class="Ih2E3d"><br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
class FTP:<br>
 &nbsp; &#39;&#39;&#39;<br>
 &nbsp; a simple ftp client<br>
 &nbsp; &#39;&#39;&#39;<br>
 &nbsp; def __init__(self, host, port):<br>
 &nbsp; &nbsp; &nbsp; &#39;&#39;&#39;<br>
 &nbsp; &nbsp; &nbsp; init<br>
 &nbsp; &nbsp; &nbsp; &#39;&#39;&#39;<br>
 &nbsp; &nbsp; &nbsp; self.__host = host<br>
 &nbsp; &nbsp; &nbsp; self.__port = port<br>
 &nbsp; &nbsp; &nbsp; self.__username = &#39;aaa&#39;<br>
 &nbsp; &nbsp; &nbsp; self.__passwd = &#39;bbb&#39;<br>
 &nbsp; &nbsp; &nbsp; self.__passive = 1<br>
<br>
 &nbsp; def __get(self, ftp_client, src, des):<br>
 &nbsp; &nbsp; &nbsp; &#39;&#39;&#39;<br>
 &nbsp; &nbsp; &nbsp; &#39;&#39;&#39;<br>
 &nbsp; &nbsp; &nbsp; save_file = SaveFile(des)<br>
 &nbsp; &nbsp; &nbsp; d = ftp_client.retrieveFile(src, save_file)<br>
 &nbsp; &nbsp; &nbsp; d = ftp_client.quit()<br>
 &nbsp; &nbsp; &nbsp; d.addCallback(lambda result: reactor.stop())<br>
 &nbsp; &nbsp; &nbsp; return d<br>
</blockquote>
<br></div>
Don&#39;t stop the reactor here. &nbsp;Stopping the reactor means your program is<br>
basically done and you don&#39;t want to do anything else with Twisted.<div class="Ih2E3d"><br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
 &nbsp; def get(self, src, des):<br>
 &nbsp; &nbsp; &nbsp; &#39;&#39;&#39;<br>
 &nbsp; &nbsp; &nbsp; get src file from ftp server, store it in des<br>
 &nbsp; &nbsp; &nbsp; &#39;&#39;&#39;<br>
 &nbsp; &nbsp; &nbsp; creator = ClientCreator(reactor, FTPClient, self.__username,<br>
self.__passwd, self.__passive)<br>
 &nbsp; &nbsp; &nbsp; defer = creator.connectTCP(self.__host,<br>
self.__port).addCallback(self.__get, src, des)<br>
 &nbsp; &nbsp; &nbsp; reactor.run()<br>
 &nbsp; &nbsp; &nbsp; return defer.result<br>
</blockquote>
<br></div>
Don&#39;t start the reactor here. &nbsp;Start the reactor in the &quot;main&quot; part of your<br>
program. &nbsp;Also, don&#39;t access &quot;defer.result&quot;. &nbsp;Instead, just return &quot;defer&quot;.<div class="Ih2E3d"><br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
 &nbsp; def __put(self, ftp_client, src, des):<br>
 &nbsp; &nbsp; &nbsp; &#39;&#39;&#39;<br>
 &nbsp; &nbsp; &nbsp; &#39;&#39;&#39;<br>
 &nbsp; &nbsp; &nbsp; source_file = os.path.basename(src)<br>
 &nbsp; &nbsp; &nbsp; target_dir = os.path.dirname(des)<br>
 &nbsp; &nbsp; &nbsp; ftp_client.changeDirectory(target_dir)<br>
 &nbsp; &nbsp; &nbsp; d = ftp_client.storeFile(src)<br>
 &nbsp; &nbsp; &nbsp; d = ftp_client.quit()<br>
 &nbsp; &nbsp; &nbsp; d.addCallback(lambda result: reactor.stop())<br>
 &nbsp; &nbsp; &nbsp; return d<br>
</blockquote>
<br></div>
Again, don&#39;t use stop here.<div class="Ih2E3d"><br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
 &nbsp;def put(self, src, des):<br>
 &nbsp; &nbsp; &nbsp; &#39;&#39;&#39;<br>
 &nbsp; &nbsp; &nbsp; put src file to ftp server, store it in des<br>
 &nbsp; &nbsp; &nbsp; &#39;&#39;&#39;<br>
 &nbsp; &nbsp; &nbsp; creator = ClientCreator(reactor, FTPClient, self.__username,<br>
self.__passwd, self.__passive)<br>
 &nbsp; &nbsp; &nbsp; defer = creator.connectTCP(self.__host,<br>
self.__port).addCallback(self.__put, src, des)<br>
 &nbsp; &nbsp; &nbsp; reactor.run()<br>
 &nbsp; &nbsp; &nbsp; return defer.result<br>
<br>
</blockquote>
<br></div>
And don&#39;t use run or .result here.<br><font color="#888888">
<br>
Jean-Paul</font><div><div></div><div class="Wj3C7c"><br>
<br>
_______________________________________________<br>
Twisted-Python mailing list<br>
<a href="mailto:Twisted-Python@twistedmatrix.com" target="_blank">Twisted-Python@twistedmatrix.com</a><br>
<a href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python" target="_blank">http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python</a><br>
</div></div></blockquote></div><br>