Chapter 17 ■ Ftp
320
The welcome message will generally have no information that could be usefully parsed by your program, but you
might want to display it if a user is calling your client interactively. The login() function can take several parameters,
including a username, password, and a third, rarely used, authentication token that FTP calls an “account.” Here it was
called without parameters, making the user log in as “anonymous” with a generic value for the password.
Recall that an FTP session can visit different directories, just like a shell prompt can move between locations with
cd. Here, the pwd() function returns the current working directory on the remote site of the connection. Finally, the
quit() function logs out and closes the connection.
Here is what the program outputs when run:
$ ./connect.py
Welcome: 220 ProFTPD Server (Bring it on...)
Current working directory: /
ASCII and Binary Files
When making an FTP transfer, you have to decide whether you want the file treated as a monolithic block of binary
data or whether you want it parsed as a text file so that your local machine can paste its lines back together using
whatever end-of-line character is native to your platform.
As you might predict, Python 3 faithfully expects and returns plain strings when you ask it to operate in text
mode, but it requires byte strings if you are handling binary file data.
A file transferred in so-called ASCII mode is delivered one line at a time and, awkwardly enough, is delivered to
your program without line endings, so that you have to glue the lines back together yourself. Take a look at Listing 17-2
for a Python program that downloads a well-known text file and saves it in your local directory.
Listing 17-2. Downloading an ASCII File
#!/usr/bin/env python3
Foundations of Python Network Programming, Third Edition
https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter17/asciidl.py
Downloads README from remote and writes it to disk.
import os
from ftplib import FTP
def main():
if os.path.exists('README'):
raise IOError('refusing to overwrite your README file')
ftp = FTP('ftp.kernel.org')
ftp.login()
ftp.cwd('/pub/linux/kernel')
with open('README', 'w') as f:
def writeline(data):
f.write(data)
f.write(os.linesep)