Why FTP in Python?
A simple FTP solution allows for any number of networking applications. Whether you need to run regular (unencrypted) backups to a remote service, or run regular downloads from the same, this guide will help you to write a simple FTP client for storing and retrieving files from an FTP server.
The first step is to import ftplib. As mentioned in the guides on building a simple web server and building a web client, the socket module is used by most every Python module that needs to interface with a port. The FTP library is no different. It relies primarily on the SOCKS module but defers to the socket module if the former is not found. The socket module ships with standard Python. The ftplib module takes care of creating the socket connection and maintaining it. So fire up your favourite text editor and enter the following:
1 import ftplib
Next, we will look at how to initiate the connection.
Initiating the Connection
Initiating the connection is almost as straightforward as running an FTP client manually. As you might expect, we need to give Python the site for the connection and any login details which the server requires. As part of telling Python the site for the connection, we also create an FTP object.
1 ftp = ftplib.FTP('ftp.myftpsite.com')
In this case, I have chosen the variable name ‘ftp’. As long as ‘ftp’ remains in lowercase or is only capitalised (e.g., ‘Ftp’), there is little chance of our confusing it with the class. Here we have created an instance of ftplib’s FTP class. That class requires, at the least, the server’s URL as an initial value and returns a socket object which we then assign to a variable. If we wanted to, we could here pass the login details and account name. The syntax for that would be:
1 handle = ftplib.FTP(<i>host</i>, <i>username</i>, <i>password</i>, <i>account_name</i>)
For purposes of illustration, we will login separately.
Logging Into the FTP Server
Having created the socket connection, we still need to log into the server. Fortunately, the FTP class also holds a method for logging into the server.
1 ftp.login("mylogin", "mypassword1")
Here we call the login with respect to the FTP object ‘ftp’. Doing this manually gives one more overt control of which account object is active when.
Next, we can actively interact with the server.
Plain Text FTP Storage and Retrieval
What you do next will depend on the reason you are opening the FTP connection. The ftplib module provides for both storage and retrieval in both binary and plain text formats.
The methods for plain text transactions are as follows:
- x.storlines(command, file) : used to store a file in line mode.
- x.retrlines(command, callback) : used to retrieve a file in line mode.
For each method, a minimum of two arguments must be passed. Each requires an explicit declaration of the command you want to execute.
For storage, the common command is ‘STOR’ with the filename. For retrieval, the common command is ‘RETR’ and the filename. You should note that these are the common commands. They are not the only ones used, so you should verify which commands are supported by the server in question.
The second part of each command is the filename in question. For programming, it is therefore common to see variable command construction as follows: [blockquote shade=”yes”] ftp.storlines(‘STOR %s’ %filename, filecontents)
You can, of course, hardwire the variables, but that would be at the cost of code flexibility.
The second argument of each method depends on what you are doing. For storage, as intimated above, the second argument is the file object itself.
For retrieval, include a callback, the function to be invoked when the file is retrieved. Here it is understood that you have created a file object for the remote file.
As the argument of the function is understood, no parentheses are necessary. An example of file retrieval in line mode is: [blockquote shade=”yes”] myfile = open(‘
ftp.retrlines(‘RETR %s’ %filename, )
FTP Storage and Retrieval in Binary Mode
The binary methods of ftplib have similar syntax:
- x.storbinary(command, file[, blocksize) : used to store a file in binary mode. x.retrbinary(command, callback[, blocksize[, rest) : used to retrieve a file in binary mode.
There are two significant points of difference between binary and text transactions. First, both binary commands allow for the optional blocksize argument. Where text transactions occur at a pre-set (and often slower) rate, binary mode is faster. By default, data is read in blocks of 8,192 bytes. However, if you know that the network will support it, you can change that when you invoke the binary method.
Second, binary retrieval supports the optional rest argument. This argument allows you to initiate downloads in the middle of a file. This function is not supported by all FTP servers. If the FTP server does not support it, an error_reply exception is raised.