[Tutor] Threaded FTP class
Kent Johnson
kent37 at tds.net
Tue Oct 10 03:10:10 CEST 2006
Bill Burns wrote:
> 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...
HTH,
Kent
More information about the Tutor
mailing list