So,
how do we write an FTP client by using Python? Here is a code
example. Let's review the steps:
- Connect to server
- Log in
- Make service request(s) (and hopefully get response[s])
- Quit
When
using Python’s FTP support, all you do is import the ftplib
module and instantiate the ftplib.FTP class. All FTP
activity—logging in, transferring files, and logging out—will be
accomplished using your object.
Here
is some Python pseudocode:
Soon
we will look at a real example, but for now, let’s familiarize
ourselves with methods from the ftplib.FTP class, which you will
likely use in your code.
ftplib.FTP
Class Methods
I
outline the most popular methods. The list is not comprehensive, but
the ones presented here are those that make up the API for FTP client
programming in Python. In other words, you don’t really need to use
the others because they are either utility or administrative
functions or are used by the API methods later.
|
Method
|
Description
|
|
login(user='anonymous',
passwd='', acct='')
|
Log
in to FTP server; all arguments are optional
|
|
pwd()
|
Current
working directory
|
|
cwd(path)
|
Change
current working directory to path
|
|
dir([path[,...[,cb]])
|
Displays
directory listing of path; optional call back cb passed to
retrlines()
|
|
nlst([path[,...])
|
Like
dir() but returns a list of filenames instead of displaying
|
|
retrlines(cmd
[, cb])
|
Download
text file given FTP cmd, for example, RETR filename; optional
callback cb for processing each line of file
|
|
retrbinary(cmd,
cb[, bs=8192[, ra]])
|
Similar
to retrlines() except for binary file; call-
back
cb for processing each block (size bs defaults
to
8K) downloaded required
|
|
storlines(cmd,
f)
|
Upload text file given FTP cmd, for example, STOR filename;
open file object f required
|
|
storbinary(cmd,
f[, bs=8192])
|
Similar to storlines() but for
binary file; open file
object f required, upload blocksize bs defaults to 8K
|
|
rename(old,
new)
|
Rename
remote file from old to new
|
|
delete(path)
|
Delete
remote file located at path
|
|
mkd(directory)
|
Create
remote directory
|
|
rmd(directory)
|
Remove
remote directory
|
|
quit()
|
Close
connection and quit
|
The
methods you will most likely use in a normal FTP transaction include
login(), cwd(), dir(), pwd(), stor*(), retr*(), and quit(). There are
more FTP object methods not listed in the table that you might find
useful. For more detailed information about FTP objects, read the
Python documentation available at
http://docs.python.org/library/ftplib#ftp-objects.
An
Interactive FTP Example
An
example of using FTP with Python is so simple to use that you do not
even have to write a script. You can just do it all from the
interactive interpreter and see the action and output in real time.
Here is a sample session, using the shell interactive python by
Terminal:
A
Client Program FTP Example
I
mentioned previously that an example script is not even necessary
because you can run one interactively and not get lost in any code. I
will try anyway. For example, suppose that you want a piece of code
that goes to download the latest copy of Bugzilla from the Mozilla
Web site. The example following, is what we came up with. I am
attempting an application here, but even so, you can probably run
this one interactively, too. Our application uses the FTP library to
download the file and includes some error-checking.
Example:
Be
aware that this script is not automated, so it is up to you to run it
whenever you want to perform the download, or if you are on a
Unix-based system, you can set up a cron job to automate it for you.
Another issue is that it will break if either the file or directory
names change.
If
no errors occur when you run this script, you get the following
output:
$
getLatestFileByFTP.py
***
Connected to host "ftp.mozilla.org"
***
Logged in as "anonymous"
***
Changed to "pub/mozilla.org/webtools" folder
***
Downloaded "bugzilla-LATEST.tar.gz" to CWD
$
Line-by-Line
Explanation
Lines
10–16
The
initial lines of code import the necessary modules (mainly to grab
exception objects) and set a few constants.
Lines
18–52
The
main() function consists of various steps of operation: create an FTP
object and attempt to connect to the FTPs server (lines 20–24) and
(return and) quit on any failure. We attempt to login as anonymous
and abort if unsuccessful (lines 27–31). The next step is to change
to the distribution directory (lines 34–39), and finally, we try to
download the file (lines 42–49).
For
line 21 and all other exception handlers in this example where you’re
saving the exception instance—in this case e—if you’re using
Python 2.5 and older, you need to change the as to a comma, because
this new syntax was introduced (but not required) in version 2.6 to
help with 3.x migration. Python 3 only understands the new syntax
shown in line 21.
On
line 42, we pass a callback to retrbinary() that should be executed
for every block of binary data downloaded. This is the write() method
of a file object we create to write out the local version of the
file. We are depending on the Python interpreter to adequately close
our file after the transfer is done and to not lose any of our data.
Although more convenient, I usually try to avoid using this style,
because the programmer should be responsible for freeing resources
directly allocated rather than depending on other code. In this case,
we should save the open file object to a variable, say loc, and then
pass loc.write in the call to ftp.retrbinary().
After
the transfer has completed, we would call loc.close(). If for some
reason we are not able to save the file, we remove the empty file to
avoid cluttering up the file system (line 45). We should put some
error-checking around that call to os.unlink(FILE) in case the file
does not exist. Finally, to avoid another pair of lines that close
the FTP connection and return, we use an else clause (lines 35–42).
Lines
46–49 This is the usual idiom for running a stand-alone script.
Conclusion:
FTP
is not only useful for downloading client applications to build
and/or use, but it can also be helpful in your everyday job for
moving files between systems. For example, suppose that you are an
engineer or a system administrator needing to transfer files. It is
an obvious choice to use the scp or rsync commands when crossing the
Internet boundary or pushing files to an externally visible server.
However, there is a penalty when moving extremely large logs or
database files between internal computers on a secure network in that
manner: security, encryption, compression/decompression, etc. If what
you want to do is just build a simple FTP application that moves
files for you quickly during the after-hours, using Python is a great
way to do it!
You
can read more about FTP in the FTP Protocol Definition/Specification
(RFC 959) at http://tools.ietf.org/html/rfc959 as well as on the www.
network sorcery.com/enp/protocol/ftp.htm Web page. Other related RFCs
include 2228, 2389, 2428, 2577, 2640, and 4217. To find out more
about Python’s FTP support, you can start at
http://docs.python.org/library/ftplib.
That's
it, see you in the next post!
Tks,











