杰瑞科技汇

如何用Python通过paramiko下载文件?

第 1 步:安装 Paramiko

你需要确保你的 Python 环境中已经安装了 paramiko 库,如果尚未安装,可以通过 pip 来安装:

如何用Python通过paramiko下载文件?-图1
(图片来源网络,侵删)
pip install paramiko

第 2 步:核心概念

paramiko 主要通过 SFTPClient (SSH File Transfer Protocol Client) 来处理文件传输,基本流程如下:

  1. 创建 SSHClient 实例:这是与服务器建立 SSH 连接的主要对象。
  2. 连接服务器:使用服务器的 IP 地址、端口、用户名和密码(或密钥)进行连接。
  3. 启动 SFTP 会话:在 SSH 连接的基础上,创建一个 SFTPClient 对象。
  4. 执行文件操作:使用 SFTPClient 的方法(如 get(), put())进行下载或上传。
  5. 关闭连接:操作完成后,关闭 SFTP 会话和 SSH 连接。

第 3 步:基本下载示例 (使用密码)

这是最常见的情况,通过用户名和密码连接服务器并下载单个文件。

假设我们要从远程服务器 /home/user/remote_file.txt 下载文件到本地 ./local_file.txt

import paramiko
import os
# --- 1. 配置连接信息 ---
hostname = 'your_server_ip'       # 远程服务器的IP地址或域名
port = 22                        # SSH端口,默认为22
username = 'your_username'       # 你的SSH用户名
password = 'your_password'       # 你的SSH密码
remote_path = '/home/user/remote_file.txt'  # 远程文件路径
local_path = './local_file.txt'  # 本地保存路径
# --- 2. 创建SSHClient对象 ---
ssh = paramiko.SSHClient()
# --- 3. 自动添加主机密钥 (不推荐用于生产环境) ---
# 第一次连接时,paramiko会询问是否接受服务器的主机密钥。
# 这行代码会自动接受并保存,方便测试,但在生产环境中存在安全风险,
# 建议使用 `ssh.load_host_keys()` 或 `ssh.set_missing_host_key_policy(paramiko.RejectPolicy())`。
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
    # --- 4. 连接服务器 ---
    print(f"正在连接到 {hostname}...")
    ssh.connect(hostname, port=port, username=username, password=password)
    print("连接成功!")
    # --- 5. 创建SFTP客户端 ---
    sftp = ssh.open_sftp()
    # --- 6. 下载文件 ---
    # sftp.get(远程路径, 本地路径)
    print(f"正在从 {remote_path} 下载文件到 {local_path}...")
    sftp.get(remote_path, local_path)
    print("文件下载成功!")
    # --- 7. 验证文件是否存在 ---
    if os.path.exists(local_path):
        print(f"本地文件 {local_path} 已创建。")
    else:
        print("本地文件未找到,下载可能失败。")
except paramiko.AuthenticationException:
    print("认证失败,请检查用户名和密码。")
except paramiko.SSHException as e:
    print(f"SSH连接或操作出错: {e}")
except Exception as e:
    print(f"发生未知错误: {e}")
finally:
    # --- 8. 关闭连接 ---
    # 确保在任何情况下都会关闭SFTP和SSH连接
    if 'sftp' in locals() and sftp:
        sftp.close()
    if 'ssh' in locals() and ssh:
        ssh.close()
        print("连接已关闭。")

第 4 步:使用 SSH 密钥进行认证 (更安全)

在生产环境中,强烈推荐使用 SSH 密钥对进行认证,而不是密码。

如何用Python通过paramiko下载文件?-图2
(图片来源网络,侵删)

你需要一个私钥文件(id_rsa)和对应的公钥(已经上传到服务器的 ~/.ssh/authorized_keys 文件中)。

import paramiko
# --- 1. 配置连接信息 ---
hostname = 'your_server_ip'
port = 22
username = 'your_username'
private_key_path = '/path/to/your/private_key'  # 你的私钥文件路径
remote_path = '/home/user/remote_file.txt'
local_path = './local_file_from_key.txt'
# --- 2. 创建SSHClient对象 ---
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
    # --- 3. 使用密钥连接 ---
    print(f"正在使用密钥连接到 {hostname}...")
    # 使用私钥文件进行连接
    ssh.connect(hostname, port=port, username=username, key_filename=private_key_path)
    print("连接成功!")
    # --- 4. 创建SFTP客户端并下载 ---
    sftp = ssh.open_sftp()
    print(f"正在从 {remote_path} 下载文件到 {local_path}...")
    sftp.get(remote_path, local_path)
    print("文件下载成功!")
except paramiko.AuthenticationException:
    print("认证失败,请检查密钥文件和权限。")
except paramiko.SSHException as e:
    print(f"SSH连接或操作出错: {e}")
except FileNotFoundError:
    print(f"错误:私钥文件 {private_key_path} 未找到。")
except Exception as e:
    print(f"发生未知错误: {e}")
finally:
    if 'sftp' in locals() and sftp:
        sftp.close()
    if 'ssh' in locals() and ssh:
        ssh.close()
        print("连接已关闭。")

第 5 步:下载整个目录

paramikoSFTPClient 没有直接提供 getdir() 方法来下载整个目录,你需要自己实现一个递归函数来遍历远程目录结构,并在本地创建对应的目录,然后逐个下载文件。

这是一个完整的示例:

import paramiko
import os
import stat
def download_directory(sftp, remote_dir, local_dir):
    """
    递归下载远程目录到本地。
    """
    print(f"正在处理远程目录: {remote_dir} -> {local_dir}")
    # 确保本地目录存在
    if not os.path.exists(local_dir):
        os.makedirs(local_dir)
        print(f"已创建本地目录: {local_dir}")
    # 遍历远程目录
    for item in sftp.listdir_attr(remote_dir):
        remote_path = os.path.join(remote_dir, item.filename)
        local_path = os.path.join(local_dir, item.filename)
        # 如果是目录,则递归下载
        if stat.S_ISDIR(item.st_mode):
            download_directory(sftp, remote_path, local_path)
        # 如果是文件,则下载
        elif stat.S_ISREG(item.st_mode):
            print(f"正在下载文件: {remote_path} -> {local_path}")
            sftp.get(remote_path, local_path)
        # 可以根据需要处理其他类型的文件(如链接、设备等)
        else:
            print(f"跳过非文件/目录项: {remote_path}")
# --- 主程序 ---
hostname = 'your_server_ip'
port = 22
username = 'your_username'
password = 'your_password'
remote_dir_path = '/home/user/remote_directory'  # 要下载的远程目录
local_dir_path = './downloaded_files'           # 本地保存目录
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
    ssh.connect(hostname, port=port, username=username, password=password)
    sftp = ssh.open_sftp()
    # 开始下载整个目录
    download_directory(sftp, remote_dir_path, local_dir_path)
    print("整个目录下载完成!")
except Exception as e:
    print(f"发生错误: {e}")
finally:
    if 'sftp' in locals() and sftp:
        sftp.close()
    if 'ssh' in locals() and ssh:
        ssh.close()
        print("连接已关闭。")

总结与最佳实践

  1. 安全第一

    如何用Python通过paramiko下载文件?-图3
    (图片来源网络,侵删)
    • 避免 AutoAddPolicy:在生产代码中,不要使用 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()),这会使你容易受到“中间人攻击”,正确做法是预先获取服务器的公钥(ssh-keyscan your_server_ip >> ~/.ssh/known_hosts),然后使用 ssh.load_host_keys('~/.ssh/known_hosts') 来加载。
    • 优先使用密钥:密钥认证比密码认证更安全。
  2. 资源管理

    • 使用 with 语句paramikoSSHClientSFTPClient 对象不支持 with 语句进行上下文管理。try...finally 块是确保连接关闭的可靠方式,务必放在 finally 块中调用 close() 方法。
  3. 错误处理

    • 捕获特定的异常,如 paramiko.AuthenticationExceptionparamiko.SSHExceptionFileNotFoundError,以便更精确地诊断问题。
  4. 进度显示

    • sftp.get() 方法本身不提供进度条,如果你需要显示下载进度,可以结合 tqdm 库,通过回调函数来实现,但这通常需要更复杂的处理,比如在传输前获取文件大小,然后在传输中更新进度条。

希望这个详细的指南能帮助你顺利使用 paramiko 进行文件下载!

分享:
扫描分享到社交APP
上一篇
下一篇