You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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_d vs put_r:put_d只会上传目录下的直接文件(不递归子目录),put_r会递归上传所有子目录和文件,根据你的需求选择即可。
  • 远程目录检查:一定要提前确保远程目标目录存在,否则会触发路径错误,sftp.exists()和sftp.makedirs()可以完美解决这个问题。

内容的提问来源于stack exchange,提问作者MdM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:21:44