[Tutor] Threaded FTP class

Bill Burns billburns at pennswoods.net
Tue Oct 10 01:32:11 CEST 2006


Hi all,

I'm trying to make a small, threaded FTP app and I'm running into
a problem.

My program has a GUI (I use PythonCard) and I want the GUI to be
responsive while network operations are going on.

I assumed that if I made a class (shown below) which was sub-classed
from threading.Thread - I wouldn't have any problems.

My GUI class (not shown) has a 'connect' button with a method that
looks like this:

def on_connect_command(self, event):
     """Connect to the remote server."""
     # getConnectData() -> returns a tuple with
     # all of the data we need to connect.
     server, username, password = self.getConnectData()
     # Instantiate my threaded FTP class.
     self.host = FTP(server, username, password)
     self.host.setDaemon(True)
     self.host.start()
     time.sleep(1)

When I hit this button, the GUI is completely responsive while trying to
connect to the remote server. I have no problems and everything works as
expected.

Here's where I get the problem... The GUI class has another method which
looks like this:

def on_getData_command(self, event):
     # getDirectoryData(...) is a method in the
     # FTP() class. It walks a remote directory.
     self.host.getDirectoryData(someDirectory)

When I fire this method - it blocks until getDirectoryData() returns,
which makes the GUI non-responsive. It's *not* hanging due to a network
problem (it will only fire if you're connected to the remote server.)

Why does this one method block? I assumed it would run in the FTP class
thread and I'd have no problems!? What should I do different?

Thanks,

Bill

A simplified version of my FTP class:

<code>

class FTP(threading.Thread):
     """This class requires ftputil which you can download
     from here -> http://ftputil.sschwarzer.net/download
     """
     def __init__(self, server, username, password):
         threading.Thread.__init__(self)
         self.server = server
         self.username = username
         self.password = password
         self.host = None
         self.connected = False

     def run(self):
         """Connects to the remote server and prints a list
         containing files and directories from the current
         directory.

         This does not block the GUI!
         """
         try:
             self.host = ftputil.FTPHost(
                                         self.server,
                                         self.username,
                                         self.password)
             data = self.getDirData()
             self.connected = True
             print data
         except ftputil.ftp_error.FTPOSError:
             self.connected = False
             print 'Could not connect to remote server!'

     def getDirData(self):
         """Returns a list containing remote 'listdir' output."""
         return [d for d in self.host.listdir(self.host.curdir)]

     def getDirectoryData(self, directory):
         """Walks the remote directory and then prints a list containing
         the files which were found.

         This blocks the GUI!
         """
         if self.connected:
             fileList = []
             self.host.chdir(directory)
             for root, dirs, files in self.host.walk(self.host.curdir):
                 for f in files:
                     fileList.append(self.host.path.abspath(
                                     self.host.path.join(root, f)))
             self.host.chdir('..')
             print fileList

     def disconnect(self):
         """Disconnect from the remote server."""
         self.host.close()
         self.connected = False

</code>




More information about the Tutor mailing list