Introduction
FTP or File Transfer Protocol is a common way to transfer files. For FTP, Python has a built in package called ftplib.
There is also a Secure File Transfer Protocol (SFTP) that uses SSH to encrypt the communication. We will focus just on traditional FTP in this guide. For SFTP you can check out the Paramiko package.
In this guide, we will look at some basic operations like:
- Connect and login to an FTP server
- List directories and files
- Upload and download files
Note these examples are all using Python 3.
Connect to an FTP server
The first thing to learn is how to connect to an FTP server. We'll look at how to connect anonymously and
- Port 21 - Default FTP port
Anonymous connection
This first example shows how to use a with
context manager
to login to an FTP server. The connection will automatically
be closed. The code will print out the welcome banner
just to ensure it connected.
# Anonymous FTP login
from ftplib import FTP
with FTP('ftp.example.com') as ftp:
print(ftp.getwelcome())
Authenticated login
If you want to authenticate, you can simply pass the user
and passwd
parameters to the FTP()
constructor or you can
call connect()
and login()
yourself. This example
shows how to login using both methods.
from ftplib import FTP
# Connect and login at once
with FTP(host='ftp.example.com', user='me', passwd='secret') as ftp:
print(ftp.getwelcome())
# Or connect and login as separate steps
ftp = FTP()
ftp.connect('ftp.example.com', 21)
ftp.login('me', 'secret')
print(ftp.getwelcome())
ftp.close()
Connect with SSL/TLS
Use the ftplib.FTP_TLS
class instead.
Note, this is not SFTP that uses SSH over port 22, this is
FTP with SSL/TLS over port 21. If your provider offers
this option, always use it over the plaintext FTP.
Then make sure you call ftplib.FTP_TLS.prot_p()
which will
setup the secure data connection.
from ftplib import FTP_TLS
# Connect to server using TLS, port 21 default. Is not SFTP over SSH
with FTP_TLS('ftp.example.com', 'user', 'secret') as ftp:
print(ftp.getwelcome())
Work with directories
Let's look first at how to do some basic operations with directories like:
- printing your current working directory
- changing directories
- creating a directory
- removing a directory
Print current working directory
Once you are connected, you will first want to know
where you are in the directory structure. The pwd()
function on the ftplib.FTP
object provides this data.
from ftplib import FTP
with FTP('ftp.example.com', 'user', 'secret') as ftp:
print(ftp.pwd()) # Usually default is /
Create a directory
You can make a directory using ftplib.FTP.mkd()
and pass
it the name of the directory. It will return a string
containing the name of the directory created.
from ftplib import FTP
with FTP('ftp.example.com', 'user', 'secret') as ftp:
ftp.mkd('my_dir')
Remove a directory
To remove a directory, just use rmd()
on your FTP object.
A directory must be empty to delete it.
from ftplib import FTP
with FTP('ftp.example.com', 'user', 'secret') as ftp:
ftp.rmd('my_dir')
Change current working directory
To switch to a different directory, use ftplib.FTP.cwd()
.
from ftplib import FTP
with FTP('ftp.example.com', 'user', 'secret') as ftp:
print(ftp.cwd('other_dir')) # Change to `other_dir/`
List directory contents
The next basic task you will probably want to do is list
the files in a directory. The ftplib.FTP.dir()
command
will list all the files in your current directory.
It does not just provide the filename though, it provides
a string that contains the permissions, whether it is a directory,
byte size, modification timestamp, owner, and group information.
It is formatted just like the output from an ls
command.
Since the output is a string, you will have to parse out the
information from it manually using split()
or regular expressions.
from ftplib import FTP
with FTP('ftp.example.com', 'user', 'secret') as ftp:
# List files
files = []
ftp.dir(files.append) # Takes a callback for each file
for f in files:
print(f)
An example file listing might look similar too:
drwxr-xr-x 3 dano dano 4096 Mar 12 23:15 www-null
Work with files
Now that we have learned how to navigate directories, it is time to learn how to:
- upload files
- download files
- get the size of a file
- rename a file
- delete a file
Upload a file
You may not be able to upload a file on every server, especially if you are only logged in anonymously. If you do have the permissions though, this example will show you how to upload a file.
For text files use storlines()
and for binary use
storbinary()
.
from ftplib import FTP
with FTP('ftp.example.com', 'user', 'pass') as ftp:
# For text or binary file, always use `rb`
with open('test.txt', 'rb') as text_file:
ftp.storlines('STOR test.txt', text_file)
with open('image.png', 'rb') as image_file:
ftp.storbinary('STOR image.png', image_file)
Get the size of a file
To check the size of a file on a remote FTP server,
you can simply use the size()
function as demonstrated
in the following example.
Depending on whether you want to check a text file
or a binary file, you want to tell the FTP server
what type you want to use. Use sendcmd()
and pass
the type with either TYPE I
for image/binary data
or TYPE A
for ASCII text.
The size()
function will return the size
of the file in bytes.
from ftplib import FTP, all_errors
with FTP('ftp.example.com', 'user', 'pass') as ftp:
try:
ftp.sendcmd('TYPE I') # "Image" or binary data
print(ftp.size('image.png')) # Get size of 'image.png' on server
except all_errors as error:
print(f"Error checking image size: {error}")
try:
ftp.sendcmd('TYPE A') # "ASCII" text
print(ftp.size('test.txt'))
except all_errors as error:
print(f"Error checking text file size: {error}")
Rename a file
To rename a file on a remote FTP server, use the rename()
function and pass the original filename and the new filename.
from ftplib import FTP, all_errors
with FTP('ftp.example.com', 'user', 'pass') as ftp:
try:
ftp.rename('test.txt', 'my_file.txt')
except all_errors as error:
print(f'Error renaming file on server: {error}')
Download a file
To download a file you can use retrlines()
or retrbinary()
on the FTP
object.
FTP.retrlines(cmd, callback=None)
FTP.retrbinary(cmd, callback, blocksize=8192, rest=None)
For the callback, we'll use write()
on the file object so
each chunk is written to the file we have open.
from ftplib import FTP, all_errors
with FTP('ftp.example.com', 'user', 'pass') as ftp:
# For text files
with open('local_test.txt', 'w') as local_file: # Open local file for writing
# Download `test.txt` from server and write to `local_file`
# Pass absolute or relative path
response = ftp.retrlines('RETR test.txt', local_file.write)
# Check the response code
# https://en.wikipedia.org/wiki/List_of_FTP_server_return_codes
if response.startswith('226'): # Transfer complete
print('Transfer complete')
else:
print('Error transferring. Local file may be incomplete or corrupt.')
# For binary use `retrbinary()`
with open('image.png', 'wb') as local_file:
ftp.retrbinary('RETR image.png', local_file.write)
Delete a file
To delete a remote file, use the delete()
function and give it the filename you want to delete. You cannot delete directories with this.
For directories, you must use rmd()
as shown in the example earlier.
from ftplib import FTP, all_errors
with FTP('ftp.example.com', 'user', 'pass') as ftp:
try:
ftp.delete('test.txt')
except all_errors as error:
print(f'Error deleting file: {error}')
Error checking
So far, none of the examples here include any exception handling. There are a few exceptions that may be thrown if the server returns an error or malformed response.
To catch everything, wrap your code with a try statement and catch all FTP exceptions with ftplib.all_errors
.
Some of the exceptions to watch for are:
ftplib.error_reply
- unexpected server replyftplib.error_temp
- temporary errorftplib.error_perm
- permanent errorftplib.error_proto
- malformed server replyftplib.all_errors
- catches all above errors that a server can return andOSError
andEOFError
.
from ftplib import FTP
with FTP('ftp.example.com', 'user', 'secret') as ftp:
try:
print(ftp.pwd())
except ftplib.all_errors as e:
print(f'Error with FTP: {e}')
Conclusion
After reading this guide, you should understand how to connect to an FTP server with or without TLS and login anonymously or as an authenticated user. You should also understand how to move around directories, create and delete directories, list files, and upload and download files from FTP.