Cannot List Ftp Directory Using Ftplib - But Ftp Client Works

Cannot list FTP directory using ftplib – but FTP client works

Status: Server sent passive reply with unroutable address

The above means that the FTP server is misconfigured. It sends its internal network IP to outside network (to the client – FileZilla or Python ftplib), where it is invalid. FileZilla can detect that and automatically fall back to the original IP address of the server.

Python ftplib does not do this kind of detection.

You need to fix your FTP server to return the correct IP address.


If it is not feasible to fix the server (it's not yours and the admin is not cooperative), you can make ftplib ignore the returned (invalid) IP address and use the original address instead by overriding FTP.makepasv:

class SmartFTP(FTP):
def makepasv(self):
invalidhost, port = super(SmartFTP, self).makepasv()
return self.host, port

ftp = SmartFTP(ftp_server)

# the rest of the code is the same

In recent versions of Python (3.6 and newer), ftplib doesn't consider the IP address in PASV response on its own.


Another solution may be to use IPv6. See Python 3.8.5 FTPS connection.

For a different problem with similar consequences, see vsftpd returns 0,0,0,0 in response to PASV.

Cannot connect to server with Python ftplib, but PuTTY Plink works

Plink is an SSH client. SSH has nothing to do with FTP. You probably want to connect with SFTP, what is a completely different protocol that runs on top of SSH.

For SFTP in Python, use Paramiko or pysftp.

Using Python's ftplib to get a directory listing, portably

Try using ftp.nlst(dir).

However, note that if the folder is empty, it might throw an error:

files = []

try:
files = ftp.nlst()
except ftplib.error_perm as resp:
if str(resp) == "550 No files found":
print "No files in this directory"
else:
raise

for f in files:
print f

Can't list files and directories using Python ftplib

Below solution worked for the @mpioski and it is working for Python 2.7.12 and Python 3.5.2 for TLS encryption.

from ftplib import FTP_TLS

# replace original makepasv function with one which always returns
# the peerhost of the control connections as peerhost for the data
# connection
_old_makepasv = FTP_TLS.makepasv
def _new_makepasv(self):
host,port = _old_makepasv(self)
host = self.sock.getpeername()[0]
return host,port
FTP_TLS.makepasv = _new_makepasv

ftp = FTP_TLS(ipAddress)
ftp.login(...)
ftp.nlst()

Following code is works for me, for non TLS encryption, we get all files listed of that location.

from ftplib import FTP
ftp = FTP(str(ftp_hostname),str(ftp_username),str(ftp_password))
ftp.cwd(str(ftp_location))
files_list = ftp.nlst()
for filename in files_list:
print(filename)

Python's FTP library connects to an IP but not its domain

ftplib docs suggest to use address without leading ftp:// I did

from ftplib import FTP
ftp = FTP()
ftp.connect('emi.nasdaq.com',21)
ftp.login()
ftp.retrlines('LIST')
ftp.quit()

and output was

07-27-13  04:30PM       <DIR>          aspnet_client
03-21-13 09:31AM <DIR> Baltic
07-21-21 02:42PM <DIR> Basic_NLS
05-21-19 08:29AM <DIR> Index
07-21-21 02:44PM <DIR> ITCH
08-21-20 02:07PM <DIR> Nasdaq Canada
08-05-19 09:31AM <DIR> Nordic
07-19-21 10:11AM <DIR> Options
12-01-20 09:49AM <DIR> Test
07-27-21 10:26AM <DIR> Web Based Reports
09-09-21 05:38PM 168 web.config

FTP upload file works manually, but fails using Python ftplib

The timeout doesn't happen until you try to send the data, so you were able to connect to the server successfully. The only difference I see is that ftplib uses passive mode by default, whereas your command-line client does not appear to. Try doing

ftp.set_pasv(False)

before initiating the transfer and see what happens.

Note that non-passive mode is essentially obsolete because it cannot be used across NAT firewalls, so you should probably configure vsFTP to allow passive mode.



Related Topics



Leave a reply



Submit