uploading test\zaurus0.jpg to zaurus0.jpg as image
uploading test\zaurus1.jpg to zaurus1.jpg as image
uploading test\zaurus2.jpg to zaurus2.jpg as image
uploading test\zoo-jan-03.jpg to zoo-jan-03.jpg as image
uploading test\zopeoutline.htm to zopeoutline.htm as text
Done: 297 files uploaded.
For my site and on my current laptop and wireless broadband connection, this process
typically takes six minutes, depending on server load. As with the download script, I
often run this command from the local directory where my web files are kept, and I
pass Python the full path to the script. When I run this on a Linux server, it works in
the same way, but the paths to the script and my web files directory differ.‡
Refactoring Uploads and Downloads for Reuse
The directory upload and download scripts of the prior two sections work as advertised
and, apart from the mimetypes logic, were the only FTP examples that were included in
the second edition of this book. If you look at these two scripts long enough, though,
their similarities will pop out at you eventually. In fact, they are largely the same—they
use identical code to configure transfer parameters, connect to the FTP server, and
determine file type. The exact details have been lost to time, but some of this code was
certainly copied from one file to the other.
Although such redundancy isn’t a cause for alarm if we never plan on changing these
scripts, it can be a killer in software projects in general. When you have two copies of
identical bits of code, not only is there a danger of them becoming out of sync over time
(you’ll lose uniformity in user interface and behavior), but you also effectively double
your effort when it comes time to change code that appears in both places. Unless you’re
a big fan of extra work, it pays to avoid redundancy wherever possible.
This redundancy is especially glaring when we look at the complex code that uses
mimetypes to determine file types. Repeating magic like this in more than one place is
almost always a bad idea—not only do we have to remember how it works every time
we need the same utility, but it is a recipe for errors.
Refactoring with functions
As originally coded, our download and upload scripts comprise top-level script code
that relies on global variables. Such a structure is difficult to reuse—code runs imme-
diately on imports, and it’s difficult to generalize for varying contexts. Worse, it’s dif-
ficult to maintain—when you program by cut-and-paste of existing code, you increase
the cost of future changes every time you click the Paste button.
‡ Usage note: These scripts are highly dependent on the FTP server functioning properly. For a while, the
upload script occasionally had timeout errors when running over my current broadband connection. These
errors went away later, when my ISP fixed or reconfigured their server. If you have failures, try running against
a different server; connecting and disconnecting around each transfer may or may not help (some servers
limit their number of connections).
884 | Chapter 13: Client-Side Scripting