运行FTP下载脚本时遭遇ftplib.error_perm:550错误,求解决
ftplib.error_perm: 550 Requested action not taken in Your FTP Script Hey there, let's break down why you're running into this 550 error and how to fix it. That error almost always means the FTP server can't find the file you're trying to download, or you don't have permission to access it. Let's start with the most likely culprit in your code: how you're parsing filenames.
The Problem with Your Filename Handling
Your current code reverses the filename string, splits on spaces, takes the first part, then reverses it again. This approach is super fragile because:
- Different FTP servers return
nlst()output in different formats—some include timestamps, file sizes, and spaces that will break your split logic. - If a filename itself contains spaces, this method will mangle it completely, leading you to request a file that doesn't exist (hence the 550 error).
Step-by-Step Fixes
1. Use a Reliable Way to Get Filenames
Instead of relying on nlst() and manual string hacking, use a method that gives you structured file information:
- MLSD (preferred): Most modern FTP servers support
MLSD, which returns standardized, machine-readable file data. - Fallback to
dir()parsing: If MLSD isn't available, parse thedir()output to grab only filenames.
Here's how to implement both:
from ftplib import FTP import os ftp = FTP() HOST = 'some host here' PORT = 21 # Pro tip: Port should be an integer, not a string! ftp.connect(host=HOST, port=PORT) ftp.login(user="some_user", passwd="pass") out = 'ftp_files/' # Make sure the local output directory exists (avoids later file write errors) os.makedirs(out, exist_ok=True) filenames = [] try: # Try MLSD first for clean, structured data for entry in ftp.mlsd(): # Only grab entries that are files (skip directories) if entry[1]['type'] == 'file': filenames.append(entry[0]) except: # Fallback to parsing dir() output if MLSD isn't supported ftp.dir(lambda line: filenames.append(line.split()[-1]))
2. Verify Permissions and File Existence
- Log into the FTP server using a desktop client (like FileZilla) with the same credentials. Try downloading the files manually—if you can't, you probably don't have read permissions for those files, or the server has restricted access.
- Double-check that the files you're trying to download exist in the FTP server's current working directory. You can run
ftp.pwd()in your script to confirm which directory you're in.
3. Clean Up the Download Loop
Update your download logic to use os.path.join() for safer path handling (avoids issues if your out path doesn't end with a slash):
for file in filenames: print(f"Downloading {file}...") local_path = os.path.join(out, file) with open(local_path, 'wb') as f: # Use an f-string for cleaner command formatting ftp.retrbinary(f'RETR {file}', f.write) ftp.close()
Full Fixed Script
Putting it all together, here's the revised script that should resolve the 550 error:
from ftplib import FTP import os ftp = FTP() HOST = 'some host here' PORT = 21 ftp.connect(host=HOST, port=PORT) ftp.login(user="some_user", passwd="pass") out = 'ftp_files/' os.makedirs(out, exist_ok=True) filenames = [] try: for entry in ftp.mlsd(): if entry[1]['type'] == 'file': filenames.append(entry[0]) except: ftp.dir(lambda line: filenames.append(line.split()[-1])) for file in filenames: print(f"Downloading {file}...") with open(os.path.join(out, file), 'wb') as f: ftp.retrbinary(f'RETR {file}', f.write) ftp.close()
内容的提问来源于stack exchange,提问作者Stanislav Goncharick

