使用 pysftp 递归下载
Recursive download with pysftp
我正在尝试从具有以下结构的 SFTP 中获取:
main_dir/
dir1/
file1
dir2/
file2
我尝试使用以下命令实现此目的:
sftp.get_r(main_path + dirpath, local_path)
或
sftp.get_d(main_path + dirpath, local_path)
本地路径如d:/grabbed_files/target_dir
,远程如/data/some_dir/target_dir
。
使用 get_r
我得到 FileNotFound
异常。使用 get_d
我得到空目录(当目标目录有文件而不是目录时,它工作正常)。
我完全确定该目录存在于此路径中。我做错了什么?
我不明白为什么它不起作用所以我以我自己的递归解决方案结束:
def grab_dir_rec(sftp, dirpath):
local_path = target_path + dirpath
full_path = main_path + dirpath
if not sftp.exists(full_path):
return
if not os.path.exists(local_path):
os.makedirs(local_path)
dirlist = sftp.listdir(remotepath=full_path)
for i in dirlist:
if sftp.isdir(full_path + '/' + i):
grab_dir_rec(sftp, dirpath + '/' + i)
else:
grab_file(sftp, dirpath + '/' + i)
如果你想要一个围绕 pysftp 的上下文管理器包装器来为你做这件事,这里有一个代码更少的解决方案(在你 copy/paste github gist) 使用时最终看起来像下面这样
path = "sftp://user:password@test.com/path/to/file.txt"
# Read a file
with open_sftp(path) as f:
s = f.read()
print s
# Write to a file
with open_sftp(path, mode='w') as f:
f.write("Some content.")
(更完整的)示例:http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html
这个上下文管理器恰好内置了自动重试逻辑,以防您第一次无法连接(令人惊讶的是,这种情况在生产环境中发生的频率比您预期的要高...)。
哦,是的,这假定每个连接只获取一个文件,因为它将自动关闭 ftp 连接。
open_sftp 的上下文管理器要点:https://gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515
这个对我有用,但是当你下载目录时,它会在本地创建完整路径。
pysftp.Connection.get_r()
我还创建了简单的 download
和 upload
方法:
def download_r(sftp, outbox):
tmp_dir = helpers.create_tmpdir()
assert sftp.isdir(str(outbox))
assert pathlib.Path(tmp_dir).is_dir()
sftp.get_r(str(outbox), str(tmp_dir))
tmp_dir = tmp_dir / outbox
return tmp_dir
def upload_r(sftp, inbox, files):
assert sftp.isdir(str(inbox))
if pathlib.Path(files).is_dir():
logger.debug(list(files.iterdir()))
sftp.put_r(str(files), str(inbox))
else:
logger.debug('No files here.')
我正在尝试从具有以下结构的 SFTP 中获取:
main_dir/
dir1/
file1
dir2/
file2
我尝试使用以下命令实现此目的:
sftp.get_r(main_path + dirpath, local_path)
或
sftp.get_d(main_path + dirpath, local_path)
本地路径如d:/grabbed_files/target_dir
,远程如/data/some_dir/target_dir
。
使用 get_r
我得到 FileNotFound
异常。使用 get_d
我得到空目录(当目标目录有文件而不是目录时,它工作正常)。
我完全确定该目录存在于此路径中。我做错了什么?
我不明白为什么它不起作用所以我以我自己的递归解决方案结束:
def grab_dir_rec(sftp, dirpath):
local_path = target_path + dirpath
full_path = main_path + dirpath
if not sftp.exists(full_path):
return
if not os.path.exists(local_path):
os.makedirs(local_path)
dirlist = sftp.listdir(remotepath=full_path)
for i in dirlist:
if sftp.isdir(full_path + '/' + i):
grab_dir_rec(sftp, dirpath + '/' + i)
else:
grab_file(sftp, dirpath + '/' + i)
如果你想要一个围绕 pysftp 的上下文管理器包装器来为你做这件事,这里有一个代码更少的解决方案(在你 copy/paste github gist) 使用时最终看起来像下面这样
path = "sftp://user:password@test.com/path/to/file.txt"
# Read a file
with open_sftp(path) as f:
s = f.read()
print s
# Write to a file
with open_sftp(path, mode='w') as f:
f.write("Some content.")
(更完整的)示例:http://www.prschmid.com/2016/09/simple-opensftp-context-manager-for.html
这个上下文管理器恰好内置了自动重试逻辑,以防您第一次无法连接(令人惊讶的是,这种情况在生产环境中发生的频率比您预期的要高...)。
哦,是的,这假定每个连接只获取一个文件,因为它将自动关闭 ftp 连接。
open_sftp 的上下文管理器要点:https://gist.github.com/prschmid/80a19c22012e42d4d6e791c1e4eb8515
这个对我有用,但是当你下载目录时,它会在本地创建完整路径。
pysftp.Connection.get_r()
我还创建了简单的 download
和 upload
方法:
def download_r(sftp, outbox):
tmp_dir = helpers.create_tmpdir()
assert sftp.isdir(str(outbox))
assert pathlib.Path(tmp_dir).is_dir()
sftp.get_r(str(outbox), str(tmp_dir))
tmp_dir = tmp_dir / outbox
return tmp_dir
def upload_r(sftp, inbox, files):
assert sftp.isdir(str(inbox))
if pathlib.Path(files).is_dir():
logger.debug(list(files.iterdir()))
sftp.put_r(str(files), str(inbox))
else:
logger.debug('No files here.')