If you’re running a server of any kind or dealing with cloud server storage, at some point you’ll probably find it necessary to use FTP. FTP stands for File Transfer Protocol and is the de facto standard for transferring files from one place to another. Python has a fully mature FTP library that any script can utilize with a simple import statement. That library, called
ftplib, is both easy to use and very useful.
- Basic familiarity with Python interactive session and scripts.
What is FTP?
FTP is a standard network protocol that allows for the transfer files from one computer to another over a network. It uses a client/server model, where the client computer makes requests of the server–requests to download or upload files, create and delete directories and files, and other common file operations. It commonly uses clear text authentication, with a simple user/password scheme, but often FTP servers are configured to allow anonymous access (to allow unlimited clients to download particular files without needing individual logins, for instance.)
Many of the most common uses of FTP are via a graphical interface, using software such as Filezilla, Cyberduck, or WinSCP. These programs make using FTP a simple matter of dragging and dropping files between servers and clients, and right-clicking for context menus. You can also use a web browser to connect to many FTP servers; the browser takes care of the actual mechanics of the FTP connection, but you lose many of the features that dedicated FTP clients have.
Getting Started with FTP in Python
You can also use FTP programmatically. Most languages have an FTP interface, and Python is no exception. One of Python’s default included modules is the
ftplib module. The
FTP class of the
ftplib module implements the client side of FTP communications. A Python client using the
FTP class can connect to an FTP server to perform a variety of tasks, such as file downloads, uploads, and even mirroring the server.
To use the
ftplib functions, we’ll need to start by importing the module. We can use one of the few free FTP servers on the net that allow anonymous logins, speedtest.tele2.net, to test the functionality of the FTP library.
Let’s experiment with using this library with a Python interactive session. Open a terminal prompt or an IDLE session, and start with the import statement at the interactive prompt (‘>>>’).
from ftplib import FTP
This statement imports the
FTP class, giving us access to all of its functionality, including
quit(). Rather than looking at each one individually, however, it may be more illustrative to interact with a live FTP server.
Now that you’ve imported the library, create a connection.
ftp = FTP('speedtest.tele2.net')
Print the default welcome connection.
print "Welcome: ", ftp.getwelcome()
You should almost immediately see the following:
Welcome: 220 (vsFTPd 2.3.5)
You should also be returned to the Python interactive prompt (‘>>>’), meaning you’ve connected to the tele2.net server. Now you can log in anonymously.
This statement should return a successful confirmation.
'230 Login successful.'
You’re now logged in, which means you can execute common file commands.
This command lists the contents of the current directory on the FTP server. You’ll see a list of various sized files you can use to test your download speed, followed by another confirmation code:
'226 Directory send OK.'
These are standard FTP codes and responses, and you can plan for those responses when you write your Python programs. Code
230, for instance, means ‘User logged in, proceed. Logged out if appropriate.’ Code
430, on the other hand, means ‘Invalid username or password’. A full list of these codes and their meanings can be found at Wikipedia.
File Transfers with the Python FTP Library
With FTP transfers, you have to determine whether the file should be treated as a single block of binary data (such as a picture or a movie file) or as a text file that your local machine can parse (such as a README file). If you were using a GUI FTP client such as Filezilla, you would choose ‘ASCII’ or ‘Binary’ for the transfer type; in Python, you use either the
retrbinary() function, respectively.
FTP ASCII Download
To experiment with the ASCII download (
retrlines()) function, let’s write a short Python script. In your text editor, enter and save the following program:
from ftplib import FTP import os def writeline(data): filedata.write(data) filedata.write(os.linesep) ftp = FTP('ftp.kernel.org') ftp.login() ftp.cwd('/pub/linux/kernel') filedata = open('README', 'w') ftp.retrlines('RETR README', writeline) filedata.close() ftp.quit()
Before we run it, let’s see what this program does, line by line.
Lines 1 and 2 import the libraries we’ll use,
Lines 4 through 6 define a method,
writeline(), to write the data we’re going to receive to our local directory, using the line separators our particular OS uses (
\n in UNIX,
\r\n in Windows).
Lines 8 and 9 define the FTP site we’re going to connect to and log in with an anonymous password. Then the
cwd() command in line 10 (similar to the Unix
cd command) moves us to the ‘/pub/linux/kernel’ directory where the file we’re after is stored.
Lines 11 through 13 open a file object (‘README’) for writing on our local machine, call
writeline() to retrieve and write the contents of the remote file into it line by line, and then close the local file.
Finally, line 15 logs us out of the remote site.
If you run this program with an active Internet connection, you should see a file called ‘README’ appear in your local directory, and be able to open it with a text editor and view the contents.
FTP Binary Download
Now, should you decide to play with binary downloads, it’s almost as simple. Suppose you wanted to download a .tar file from the same kernel.org site. Let’s rewrite our script like so:
from ftplib import FTP import os ftp = FTP('ftp.kernel.org') ftp.login() ftp.cwd('/pub/linux/kernel/v1.0') filedata = open('patch1.gz', 'wb') ftp.retrbinary('RETR patch1.gz', filedata.write) filedata.close() ftp.quit()
Here, everything is nearly the same, with a few exceptions.
retrlines(), you’re using the
retrbinary() function, and no special
write function is necessary. Also, note that our
open() function includes ‘b’ with ‘w’ to indicate we’ll be writing binary.
When you run this script, you’ll see the ‘patch1.gz’ file appear in your local directory.
Thank you for following along with this introduction to using Python’s FTP library. Please check back with us again for updates and further tutorials dealing with text and binary uploads, recursive downloading, common file operations, and error handling.