--- tags: - python - ftp - sftp --- # 🚀 Python 操作 SFTP 和 FTP 完全指南 本文提供 Python 操作 SFTP 和 FTP 的
tags:
🚀 Python 操作 SFTP 和 FTP 完全指南
本文提供 Python 操作 SFTP 和 FTP 的完整解决方案,涵盖连接管理、文件传输、目录操作等核心功能。
📌 核心库对比
| 功能 |
SFTP (推荐库) |
FTP (推荐库) |
| 基础库 |
paramiko |
ftplib (标准库) |
| 高级功能 |
pysftp (基于paramiko) |
ftputil (增强版) |
| TLS/SSL支持 |
内置 |
ftplib.FTP_TLS |
| 主要优势 |
SSH加密传输 |
标准库无需安装 |
| 适用场景 |
安全传输、自动化 |
简单文件传输、内部网络 |
🔐 SFTP 操作指南 (使用 Paramiko)
安装依赖
基础连接与文件操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
import paramiko
from paramiko import SSHClient, AutoAddPolicy
def sftp_demo():
host = "sftp.example.com"
port = 22
username = "your_username"
password = "your_password"# 或使用密钥
# 创建SSH客户端
ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
try:
# 建立连接
ssh.connect(host, port, username, password)
# 创建SFTP客户端
sftp = ssh.open_sftp()
# 1. 上传文件
sftp.put("local_file.txt", "/remote/path/file.txt")
# 2. 下载文件
sftp.get("/remote/path/file.txt", "local_copy.txt")
# 3. 创建目录
sftp.mkdir("/remote/new_folder")
# 4. 列出目录内容
file_list = sftp.listdir("/remote/path")
print("目录内容:", file_list)
# 5. 删除文件
sftp.remove("/remote/path/old_file.txt")
# 6. 重命名文件
sftp.rename("/remote/path/old_name.txt", "/remote/path/new_name.txt")
# 7. 获取文件信息
file_attr = sftp.stat("/remote/path/file.txt")
print(f"文件大小: {file_attr.st_size} bytes")
except Exception as e:
print(f"SFTP操作失败: {str(e)}")
finally:
# 关闭连接
sftp.close()
ssh.close()
sftp_demo()
|
高级功能 - 递归上传目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
def sftp_upload_dir(sftp, local_dir, remote_dir):
"""递归上传整个目录"""
import os
# 确保远程目录存在
try:
sftp.mkdir(remote_dir)
except IOError:
pass# 目录已存在
# 遍历本地目录
for item in os.listdir(local_dir):
local_path = os.path.join(local_dir, item)
remote_path = remote_dir + "/" + item
if os.path.isfile(local_path):
sftp.put(local_path, remote_path)
print(f"上传文件: {local_path} -> {remote_path}")
elif os.path.isdir(local_path):
sftp_upload_dir(sftp, local_path, remote_path)
|
使用 SSH 密钥认证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
def sftp_with_key():
host = "sftp.example.com"
username = "your_username"
private_key_path = "/path/to/private_key.pem"
# 加载私钥
key = paramiko.RSAKey.from_private_key_file(private_key_path)
ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(host, username=username, pkey=key)
sftp = ssh.open_sftp()
# ...后续操作同上
|
📁 FTP 操作指南 (使用 ftplib)
基础连接与文件操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
from ftplib import FTP, FTP_TLS
import os
def ftp_demo():
host = "ftp.example.com"
username = "your_username"
password = "your_password"
try:
# 创建FTP连接
ftp = FTP(host)
ftp.login(username, password)
print(ftp.getwelcome())# 打印欢迎信息
# 1. 上传文件
with open("local_file.txt", "rb") as f:
ftp.storbinary("STOR remote_file.txt", f)
# 2. 下载文件
with open("local_copy.txt", "wb") as f:
ftp.retrbinary("RETR remote_file.txt", f.write)
# 3. 列出目录内容
files = []
ftp.dir(files.append)# 列出当前目录
print("目录内容:", files)
# 4. 创建目录
ftp.mkd("new_folder")
# 5. 切换目录
ftp.cwd("subdirectory")
# 6. 删除文件
ftp.delete("old_file.txt")
# 7. 重命名文件
ftp.rename("old_name.txt", "new_name.txt")
# 8. 获取文件大小
size = ftp.size("remote_file.txt")
print(f"文件大小: {size} bytes")
except Exception as e:
print(f"FTP操作失败: {str(e)}")
finally:
ftp.quit()
ftp_demo()
|
使用 TLS/SSL 加密 (FTPS)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
def ftps_demo():
host = "ftps.example.com"
username = "your_username"
password = "your_password"
try:
# 创建加密连接
ftp = FTP_TLS(host)
ftp.login(username, password)
ftp.prot_p()# 切换到加密数据连接
# 后续操作与普通FTP相同...
with open("local_file.txt", "rb") as f:
ftp.storbinary("STOR secure_file.txt", f)
finally:
ftp.quit()
|
递归下载目录 (高级)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
def ftp_download_dir(ftp, remote_dir, local_dir):
"""递归下载整个目录"""
import os
# 创建本地目录
if not os.path.exists(local_dir):
os.makedirs(local_dir)
# 切换到远程目录
ftp.cwd(remote_dir)
# 获取文件列表
files = []
ftp.retrlines('LIST', files.append)
for line in files:
# 解析FTP列表行
parts = line.split()
filename = parts[-1]
# 跳过特殊目录
if filename in ['.', '..']:
continue
# 处理目录
if line.startswith('d'):
ftp_download_dir(ftp, filename, os.path.join(local_dir, filename))
# 处理文件
else:
local_path = os.path.join(local_dir, filename)
with open(local_path, 'wb') as f:
ftp.retrbinary(f'RETR {filename}', f.write)
print(f"下载文件: {filename}")
# 返回上级目录
ftp.cwd('..')
|
🛡️ 安全最佳实践
- 连接安全
- SFTP优先于FTP
- 使用FTPS代替普通FTP
- 禁用FTP明文传输
- 认证安全
1
2
3
4
5
6
7
|
# 避免密码硬编码
import getpass
password = getpass.getpass("Enter SFTP password: ")
# 或使用环境变量
import os
password = os.environ.get("SFTP_PASSWORD")
|
- 错误处理
1
2
3
4
5
6
7
8
9
10
|
from paramiko import SSHException
try:
# SFTP操作代码
except SSHException as ssh_err:
print(f"SSH错误: {ssh_err}")
except IOError as io_err:
print(f"文件操作错误: {io_err}")
except Exception as e:
print(f"未知错误: {e}")
|
🧪 测试工具推荐
- 本地测试服务器
- SFTP:
sudo apt-get install openssh-server
- FTP:
sudo apt-get install vsftpd
- Python测试库
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# SFTP测试
from unittest.mock import patch, MagicMock
def test_sftp_upload():
with patch('paramiko.SSHClient') as mock_ssh:
mock_sftp = MagicMock()
mock_ssh.return_value.open_sftp.return_value = mock_sftp
# 调用上传函数
sftp_upload_file("test.txt", "/remote/test.txt")
# 验证是否调用上传
mock_sftp.put.assert_called_with("test.txt", "/remote/test.txt")
|
🚀 性能优化技巧
- 大文件传输
1
2
3
4
5
6
7
|
# 使用缓冲区优化大文件传输
BUFFER_SIZE = 1024 * 1024# 1MB
def sftp_upload_large_file(local_path, remote_path):
with open(local_path, 'rb') as f:
sftp.putfo(f, remote_path, file_size=os.path.getsize(local_path),
callback=None, confirm=True)
|
- 并行传输
1
2
3
4
5
6
7
8
9
10
|
from concurrent.futures import ThreadPoolExecutor
def parallel_upload(files):
with ThreadPoolExecutor(max_workers=5) as executor:
futures = []
for local, remote in files:
futures.append(executor.submit(sftp.put, local, remote))
for future in futures:
future.result()# 等待所有任务完成
|
📚 扩展学习资源
- 官方文档
- 替代库
pysftp:更简单的SFTP封装
ftputil:增强版FTP客户端
fabric:自动化部署工具(包含SFTP)
- 相关协议
- SCP:
scp 模块 (基于paramiko)
- WebDAV:
webdavclient3 库
- Cloud Storage:boto3 (AWS S3), google-cloud-storage
💡 总结
| 任务 |
SFTP (Paramiko) |
FTP (ftplib) |
| 基础连接 |
SSHClient().connect() |
FTP().login() |
| 安全传输 |
内置 |
需用FTP_TLS |
| 文件上传 |
.put() |
.storbinary() |
| 文件下载 |
.get() |
.retrbinary() |
| 目录操作 |
.listdir() .mkdir() |
.dir() .mkd() |
| 递归操作 |
需自定义 |
需自定义 |
| 最佳场景 |
安全关键型传输 |
内部网络简单传输 |
根据您的安全需求选择协议:
- 需要加密传输:优先使用 SFTP
- 仅内部网络:可使用普通 FTP
- 需要合规性:使用 SFTP 或 FTPS
提示:实际应用中建议将连接管理封装为类,支持连接池和自动重连机制。