如何解决ftplib.error_perm:550文件被占用导致的FTP上传失败问题
解决FTP上传时
ftplib.error_perm: 550文件被占用的问题 看起来你遇到的这个550错误有点棘手,结合你提供的代码和场景,我来拆解下可能的原因并给出具体的解决办法~
错误原因分析
这个错误提示虽然说“文件被其他进程占用”,但在FTP上传场景下可能有几种诱因:
- 本地端:图片文件还没完全写入磁盘(比如生成图片的进程还在flush数据)、被杀毒软件/其他工具扫描锁定
- 服务器端:上次上传失败留下的残损文件被服务器进程占用、目标文件正在被其他操作处理
- 网络问题:上传中途断连导致服务器端文件处于半打开状态
针对性解决方案
1. 确保本地文件可安全读取
你已经通过检查jpg结尾的\xff\xd9来验证文件完整性,但有时候即使结尾正确,文件可能还被其他进程占用。可以给文件读取加重试逻辑:
import time def get_safe_file_handle(file_path, max_retries=3, retry_delay=1): """尝试多次获取文件句柄,处理本地文件占用问题""" for retry in range(max_retries): try: return open(file_path, 'rb') except PermissionError: print(f"文件 {file_path} 被占用,{retry_delay}秒后重试...") time.sleep(retry_delay) raise RuntimeError(f"多次尝试后仍无法打开文件:{file_path}")
2. 给FTP上传加重试机制(适配网络不稳定+服务器端占用)
针对上传过程中出现的550错误或网络中断,我们可以:
- 重试上传前先尝试删除服务器上的目标文件(清理残损文件)
- 捕获相关异常并自动重试
- 连接断开时自动重新登录FTP
修改你的上传逻辑为带重试的函数:
import ftplib import socket def upload_with_retry(ftp, local_path, remote_filename, cut_switch, max_retries=3, retry_delay=2): """带重试的FTP上传函数""" for attempt in range(1, max_retries+1): try: # 先尝试删除服务器上可能存在的残损文件 try: ftp.delete(remote_filename) print(f"已删除服务器上的旧文件:{remote_filename}") except ftplib.error_perm: # 文件不存在时忽略该错误 pass # 执行上传逻辑 print(f"第 {attempt} 次尝试上传:{remote_filename}") if cut_switch: img = Cut_image(local_path) ftp.storbinary(f'STOR {remote_filename}', img) else: with get_safe_file_handle(local_path) as imageReader: ftp.storbinary(f'STOR {remote_filename}', imageReader) print(f"上传成功:{remote_filename}") return True except (ftplib.error_perm, socket.error, ConnectionResetError) as e: print(f"第 {attempt} 次上传失败:{str(e)}") time.sleep(retry_delay) # 检查FTP连接是否存活,断开则重新登录 try: ftp.voidcmd('NOOP') # 发送空命令验证连接 except ftplib.error_temp: print("FTP连接已断开,重新登录...") ftp.login(your_username, your_password) # 替换为你的FTP账号密码 print(f"经过 {max_retries} 次重试后,仍无法上传文件:{remote_filename}") return False
3. 整合到你的现有代码中
把原来的上传部分替换成这个重试函数即可:
# 检查文件完整性 with open(img_list[0][0], "rb") as oFile: check_chars = oFile.read()[-2:] if check_chars != b"\xff\xd9": print(f"文件不完整,跳过:{img_list[0][1]}") time.sleep(1) continue print("準備上傳: %s" % img_list[0][1]) # 调用带重试的上传函数 upload_with_retry(ftp, img_list[0][0], img_list[0][1], cut_switch)
额外优化建议
- 增加日志记录:把上传的成功/失败信息写入日志文件,方便后续排查问题
- 批量上传控制:如果是大量图片,不要一次性同时上传太多,避免触发服务器的并发限制
- 服务器端文件检查:上传前可以用
ftp.size(remote_filename)检查目标文件是否存在且大小正常,再决定是覆盖还是跳过
内容的提问来源于stack exchange,提问作者burstknight
相关产品推荐
相关产品推荐

