[Tutor] Threaded FTP class

Bill Burns billburns at pennswoods.net
Tue Oct 10 03:28:05 CEST 2006


>> 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.
> 
> 
> In this method you create a new thread and start it. The thread's run() 
> method is called. It connects to the remote server, fetches and prints a 
> directory and returns. At that point (when the run() method returns) the 
> FTP thread is dead.
> 
>>
>> 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?
> 
> 
> No, you don't do anything here to make the getDirectoryData() method run 
> in a separate thread. Just because the FTP class has (or had) one thread 
> at one time doesn't automatically make all of the FTP class methods run 
> in a different thread.
> 
> There are a few different ways you could handle this. You could have 
> each command in the FTP class be smart enough to start a new thread to 
> run the command. You don't actually have to subclass threading.Thread, 
> you can just create a thread and tell it what method to execute. (Side 
> note - this might be a good use for a @run_in_thread decorator.)
> 
> You could make a separate class for each command. This would be pretty 
> similar to the above solution. You would probably want a base class or 
> utility class to hold the common details of connecting and sending a 
> command.
> 
> You could make a thread that really does keep running, that listens to 
> for commands from a Queue. Your GUI thread would put a command in the 
> Queue, the daemon thread would pull a command out and execute it.
> 
> You could figure out how to do this with Twisted...
> 


Kent,

Thank you for the explanation and ideas!! I wasn't exactly sure how the 
threading was working but you've enlightened me!

Bill



More information about the Tutor mailing list