Windows系统下pysftp put_r无法使用问题求助
解决pysftp 0.2.8上传Windows目录时的OSError: Invalid Path问题
我之前用pysftp做SFTP上传的时候也踩过类似的路径错误坑,帮你梳理下问题根源和解决办法:
问题根源
你遇到的OSError: Invalid path主要是因为对put_r的参数逻辑理解有误,再加上已经通过cd切换了远程目录,导致路径冲突:
- 你已经用
sftp.cd(sftp_remote_path)切换到了目标远程目录,这时候再把完整的远程路径传给put_r的第二个参数,会让pysftp尝试访问一个重复拼接的无效路径(比如/FTP/LPS Data/.../XML/FTP/LPS Data/.../XML)。 - 另外如果远程目标目录不存在,
put_r也会抛出路径错误,因为它默认不会自动创建目录。
解决方案
方案1:切换远程目录后上传(最直观)
既然已经切换到目标远程目录,put_r的第二个参数直接用.(表示当前目录)或者省略即可,这样就能把本地目录的内容递归上传到当前远程目录:
import pysftp sftp_local_path = r'C:\Users\Swiss\some\path' sftp_remote_path = '/FTP/LPS Data/ATC/RAND/20191019_RAND/XML' with pysftp.Connection("xxx.xxx.xxx.xxx", username=myUsername, password=myPassword) as sftp: # 先检查远程目录是否存在,不存在则递归创建 if not sftp.exists(sftp_remote_path): sftp.makedirs(sftp_remote_path) # 切换到目标远程目录 with sftp.cd(sftp_remote_path): # 上传本地目录所有内容到当前远程目录(递归) sftp.put_r(sftp_local_path, '.') # 验证上传结果 for item in sftp.listdir(): lstat_info = str(sftp.lstat(item)).split()[0] if 'd' in lstat_info: print(f"{item} is a directory") # 不需要手动调用sftp.close(),with上下文管理器会自动处理连接关闭
方案2:直接指定完整远程路径上传
如果你不想切换目录,可以直接把完整的远程目标目录传给put_r,pysftp会把本地目录的内容上传到这个指定路径下:
import pysftp sftp_local_path = r'C:\Users\Swiss\some\path' sftp_remote_path = '/FTP/LPS Data/ATC/RAND/20191019_RAND/XML' with pysftp.Connection("xxx.xxx.xxx.xxx", username=myUsername, password=myPassword) as sftp: if not sftp.exists(sftp_remote_path): sftp.makedirs(sftp_remote_path) # 直接上传本地目录到指定远程目录 sftp.put_r(sftp_local_path, sftp_remote_path) # 验证上传结果 sftp.cd(sftp_remote_path) for item in sftp.listdir(): lstat_info = str(sftp.lstat(item)).split()[0] if 'd' in lstat_info: print(f"{item} is a directory")
方案3:上传指定文件(而非整个目录)
如果只需要上传特定类型的文件(比如所有.xml文件),可以遍历本地目录,用put方法逐个上传:
import pysftp import os sftp_local_path = r'C:\Users\Swiss\some\path' sftp_remote_path = '/FTP/LPS Data/ATC/RAND/20191019_RAND/XML' with pysftp.Connection("xxx.xxx.xxx.xxx", username=myUsername, password=myPassword) as sftp: if not sftp.exists(sftp_remote_path): sftp.makedirs(sftp_remote_path) with sftp.cd(sftp_remote_path): # 遍历本地目录,筛选并上传指定文件 for filename in os.listdir(sftp_local_path): if filename.endswith('.xml'): local_file_path = os.path.join(sftp_local_path, filename) sftp.put(local_file_path) print(f"成功上传:{filename}")
关键注意事项
- 路径分隔符:Windows的
\和SFTP的/不需要手动转换,pysftp会自动处理本地路径的分隔符。 put_dvsput_r:put_d只会上传目录下的直接文件(不递归子目录),put_r会递归上传所有子目录和文件,根据你的需求选择即可。- 远程目录检查:一定要提前确保远程目标目录存在,否则会触发路径错误,
sftp.exists()和sftp.makedirs()可以完美解决这个问题。
内容的提问来源于stack exchange,提问作者MdM
相关产品推荐
相关产品推荐

