使用SFTP在Python中上传文件,若路径不存在则创建目录
我想用Python把一个文件上传到远程服务器上。在上传之前,我想先检查一下远程路径是否真的存在,如果不存在的话,就创建这个路径。大概的想法是这样的:
if(remote_path not exist):
create_path(remote_path)
upload_file(local_file, remote_path)
我在想用Paramiko执行一个命令来创建这个路径,比如说 mkdir -p remote_path
。我想出了这个方法:
# I didn't test this code
import paramiko, sys
ssh = paramiko.SSHClient()
ssh.connect(myhost, 22, myusername, mypassword)
ssh.exec_command('mkdir -p ' + remote_path)
ssh.close
transport = paramiko.Transport((myhost, 22))
transport.connect(username = myusername, password = mypassword)
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.put(local_path, remote_path)
sftp.close()
transport.close()
但是我觉得这个方法不太好,因为我先关闭了连接,然后又重新打开。有没有更好的办法呢?
7 个回答
7
今天我需要做这个。下面是我怎么做的。
def mkdir_p(sftp, remote_directory):
dir_path = str()
for dir_folder in remote_directory.split("/"):
if dir_folder == "":
continue
dir_path += r"/{0}".format(dir_folder)
try:
sftp.listdir(dir_path)
except IOError:
sftp.mkdir(dir_path)
12
这段代码更简单,而且稍微容易读懂一些。
def mkdir_p(sftp, remote, is_dir=False):
"""
emulates mkdir_p if required.
sftp - is a valid sftp object
remote - remote path to create.
"""
dirs_ = []
if is_dir:
dir_ = remote
else:
dir_, basename = os.path.split(remote)
while len(dir_) > 1:
dirs_.append(dir_)
dir_, _ = os.path.split(dir_)
if len(dir_) == 1 and not dir_.startswith("/"):
dirs_.append(dir_) # For a remote path like y/x.txt
while len(dirs_):
dir_ = dirs_.pop()
try:
sftp.stat(dir_)
except:
print "making ... dir", dir_
sftp.mkdir(dir_)
66
SFTP支持常见的FTP命令,比如改变目录(chdir)、创建目录(mkdir)等等,所以可以直接使用这些命令:
sftp = paramiko.SFTPClient.from_transport(transport)
try:
sftp.chdir(remote_path) # Test if remote_path exists
except IOError:
sftp.mkdir(remote_path) # Create remote_path
sftp.chdir(remote_path)
sftp.put(local_path, '.') # At this point, you are in remote_path in either case
sftp.close()
如果你想完全模拟mkdir -p
的功能,可以通过递归的方式处理远程路径:
import os.path
def mkdir_p(sftp, remote_directory):
"""Change to this directory, recursively making new folders if needed.
Returns True if any folders were created."""
if remote_directory == '/':
# absolute path so change directory to root
sftp.chdir('/')
return
if remote_directory == '':
# top-level relative directory must exist
return
try:
sftp.chdir(remote_directory) # sub-directory exists
except IOError:
dirname, basename = os.path.split(remote_directory.rstrip('/'))
mkdir_p(sftp, dirname) # make parent directories
sftp.mkdir(basename) # sub-directory missing, so created it
sftp.chdir(basename)
return True
sftp = paramiko.SFTPClient.from_transport(transport)
mkdir_p(sftp, remote_path)
sftp.put(local_path, '.') # At this point, you are in remote_path
sftp.close()
当然,如果远程路径中还包含一个远程文件名,那么需要把它分开,目录部分传给mkdir_p,而文件名则用在sftp.put的地方,替代掉'.'。