使用Python从SFTP文件夹删除文件时遇异常求助
问题排查:SFTP删除文件时报"Bad message"错误
核心问题
已实现远程文件下载到本地、再上传至同级备份文件夹的流程,但执行sftp.remove(file_path)时触发如下错误:
Error reading file test_abs_2022135201552.pslog: Bad message
get和put功能正常,需求为单个文件处理完成后立即删除,而非批量操作。
排查与解决方向
1. 检查文件路径的正确性
代码片段存在明显逻辑遗漏:
- 执行
remote_files = sftp.listdir(station_folder_path)后,缺少遍历remote_files的循环(即for file in remote_files:),直接使用file变量会导致未定义错误。 file_path必须是远程服务器的完整路径,需用os.path.join(station_folder_path, file)拼接,仅传文件名会导致SFTP找不到目标文件。
2. 排查文件权限或锁定状态
- 部分SFTP服务器在文件传输完成后会短暂锁定文件,导致立即删除失败,可尝试在
remove前添加短暂延迟(如time.sleep(1)),但更稳妥的方式是确认服务器端是否存在文件锁定机制。 - 验证SFTP用户对原文件所在目录是否拥有删除权限,部分服务器仅开放读取权限,也会返回模糊的"Bad message"错误。
3. 验证Paramiko版本与服务器兼容性
- 旧版本Paramiko可能与特定SFTP服务器(如特定版本OpenSSH、商用SFTP服务)存在兼容性问题,建议升级至最新稳定版:
pip install --upgrade paramiko - 先用原生SFTP命令行测试删除操作:
若命令行可正常删除,问题大概率出在Paramiko代码或版本;若命令行也报错,则是服务器端问题(权限、文件状态等)。sftp user@your-sftp-host rm /path/to/your/file.pslog
4. 修正代码逻辑中的错误
补全循环、修正变量名与路径拼接后的示例代码:
source_path = "/project/" local_path = r'C:\Users\Desktop\project' df_staging = pd.DataFrame() def main(): transport = paramiko.Transport((sftp_host, sftp_port)) transport.connect(username=sftp_username, password=sftp_password) sftp = paramiko.SFTPClient.from_transport(transport) global df_staging try: main_folders = sftp.listdir(source_path) for main_folder in main_folders: main_folder_path = os.path.join(source_path, main_folder) # 修正变量名 station_folders = sftp.listdir(main_folder_path) # 创建远程备份文件夹 backup_folder_path = os.path.join(main_folder_path, 'backup') if 'backup' not in sftp.listdir(main_folder_path): sftp.mkdir(backup_folder_path) print("Backup folder created") # 创建本地文件夹(用exists替代listdir判断更可靠) local_main_folder = os.path.join(local_path, main_folder) if not os.path.exists(local_main_folder): os.mkdir(local_main_folder) for station_folder in station_folders: if station_folder != 'backup': station_folder_path = os.path.join(main_folder_path, station_folder) remote_files = sftp.listdir(station_folder_path) # 补全遍历文件的循环 for file in remote_files: file_path = os.path.join(station_folder_path, file) # 拼接完整远程路径 local_file_path = os.path.join(local_main_folder, file) remote_backup_path = os.path.join(backup_folder_path, file) try: # 下载文件 sftp.get(file_path, local_file_path) # 上传到备份文件夹 sftp.put(local_file_path, remote_backup_path) # 删除原文件 sftp.remove(file_path) print(f"Done transferring and deleting: {file} ") except Exception as e: print(f"Error processing file {file}: {str(e)}") finally: # 可选:清理本地临时文件 if os.path.exists(local_file_path): os.remove(local_file_path) except Exception as e: print(f"Main process error: {str(e)}") finally: # 确保连接关闭 sftp.close() transport.close()
内容的提问来源于stack exchange,提问作者Jolin
相关产品推荐
相关产品推荐

