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

pip install paramiko
第 2 步:核心概念
paramiko 主要通过 SFTPClient (SSH File Transfer Protocol Client) 来处理文件传输,基本流程如下:
- 创建 SSHClient 实例:这是与服务器建立 SSH 连接的主要对象。
- 连接服务器:使用服务器的 IP 地址、端口、用户名和密码(或密钥)进行连接。
- 启动 SFTP 会话:在 SSH 连接的基础上,创建一个
SFTPClient对象。 - 执行文件操作:使用
SFTPClient的方法(如get(),put())进行下载或上传。 - 关闭连接:操作完成后,关闭 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 密钥对进行认证,而不是密码。

你需要一个私钥文件(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 步:下载整个目录
paramiko 的 SFTPClient 没有直接提供 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("连接已关闭。")
总结与最佳实践
-
安全第一:
(图片来源网络,侵删)- 避免
AutoAddPolicy:在生产代码中,不要使用ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()),这会使你容易受到“中间人攻击”,正确做法是预先获取服务器的公钥(ssh-keyscan your_server_ip >> ~/.ssh/known_hosts),然后使用ssh.load_host_keys('~/.ssh/known_hosts')来加载。 - 优先使用密钥:密钥认证比密码认证更安全。
- 避免
-
资源管理:
- 使用
with语句:paramiko的SSHClient和SFTPClient对象不支持with语句进行上下文管理。try...finally块是确保连接关闭的可靠方式,务必放在finally块中调用close()方法。
- 使用
-
错误处理:
- 捕获特定的异常,如
paramiko.AuthenticationException、paramiko.SSHException和FileNotFoundError,以便更精确地诊断问题。
- 捕获特定的异常,如
-
进度显示:
sftp.get()方法本身不提供进度条,如果你需要显示下载进度,可以结合tqdm库,通过回调函数来实现,但这通常需要更复杂的处理,比如在传输前获取文件大小,然后在传输中更新进度条。
希望这个详细的指南能帮助你顺利使用 paramiko 进行文件下载!
