使用pysftp.put上传文件时,文件已上传仍抛出“No such file”异常
解决pysftp上传偶发异常的问题
先来看你的上传代码:
cnopts = pysftp.CnOpts() cnopts.hostkeys = None self.sftp = pysftp.Connection(host=self.serverConnectionAuth['host'], port=self.serverConnectionAuth['port'], username=self.serverConnectionAuth['username'], password=self.serverConnectionAuth['password'], cnopts=cnopts) self.sftp.put(localpath=self.filepath+filename, remotepath=filename)
这段代码多数场景下能正常运行,但偶发异常通常和几个常见的坑有关,我来逐一拆解并给出解决方案:
1. 未正确回收连接导致资源泄漏
你当前的代码没有显式关闭SFTP连接,如果程序频繁执行或者连接未被及时回收,很可能导致服务器端连接数耗尽,进而触发偶发的连接/上传失败。
优化方案:用上下文管理器(with语句)自动管理连接,无论上传成功还是失败,连接都会被正确关闭:
cnopts = pysftp.CnOpts() cnopts.hostkeys = None with pysftp.Connection(host=self.serverConnectionAuth['host'], port=self.serverConnectionAuth['port'], username=self.serverConnectionAuth['username'], password=self.serverConnectionAuth['password'], cnopts=cnopts) as sftp: sftp.put(localpath=self.filepath+filename, remotepath=filename)
2. 网络波动引发的连接中断
偶发异常最常见的诱因就是网络不稳定——短暂丢包、延迟过高都可能导致SFTP会话超时或中断。
优化方案:
- 增加连接超时参数:在
Connection中添加timeout=30(单位秒),避免无限等待; - 加入重试机制:针对网络类异常捕获并重试,比如:
import pysftp from paramiko.ssh_exception import SSHException import time def upload_with_retry(max_retries=3): retries = 0 while retries < max_retries: try: cnopts = pysftp.CnOpts() cnopts.hostkeys = None with pysftp.Connection(host=self.serverConnectionAuth['host'], port=self.serverConnectionAuth['port'], username=self.serverConnectionAuth['username'], password=self.serverConnectionAuth['password'], cnopts=cnopts, timeout=30) as sftp: sftp.put(localpath=self.filepath+filename, remotepath=filename) return True except (SSHException, OSError) as e: retries += 1 time.sleep(2) # 重试前等待2秒,给网络恢复时间 if retries == max_retries: raise e
3. 禁用HostKey验证的潜在隐患
你设置cnopts.hostkeys = None绕过了主机密钥验证,这不仅会让连接暴露在中间人攻击风险中,部分服务器还会对无密钥验证的连接施加额外限制,偶尔导致连接失败。
优化方案:如果允许的话,建议正确配置主机密钥:
- 先手动连接一次目标服务器,将主机密钥保存到本地(比如
~/.ssh/known_hosts); - 代码中加载主机密钥而非直接禁用:
cnopts = pysftp.CnOpts() # 也可以指定自定义的known_hosts路径 # cnopts.hostkeys.load('/path/to/your/known_hosts') self.sftp = pysftp.Connection(...)
4. 文件路径拼接的可靠性问题
你用self.filepath+filename拼接本地路径,如果self.filepath末尾没有斜杠,可能会生成错误路径(比如/home/userfile.txt而非/home/user/file.txt),虽然多数系统能兼容,但特殊文件名或环境下可能触发异常。
优化方案:用os.path.join来拼接路径,适配不同系统的路径规则:
import os local_path = os.path.join(self.filepath, filename) sftp.put(localpath=local_path, remotepath=filename)
如果能提供具体的异常信息,还能更精准定位问题,但以上几点是pysftp上传偶发异常的高频诱因,你可以先尝试这些优化。
内容的提问来源于stack exchange,提问作者Amir Zare
相关产品推荐
相关产品推荐

