python sftp ftp 造轮子,实现多个方法

SFTP 与 FTP

python中对于sftp与ftp的支持较少,很多方法都没有,如makedirs与exists检查,只能自己造轮子了,废话不多说,直接上代码。

class SFTP_obj

import paramiko
import os
import time



class SFTP_obj():

    def action_try(fun):
        def wrapper(*args, **kwargs):  # def 与 return 之后的函数名称一致
            try:
                ret = fun(*args, **kwargs)
                return ret  # return ret 与 ret=func(*args,**kwargs)一致
            except Exception as error:
                print('函数 ' + fun.__name__ + ' 操作失败',end='    ')
                print(error)
                #print(traceback.print_exc())
                #print('函数'+fun.__name__+'操作失败')
        return wrapper

    def __init__(self, host, username, password):
        self.host = host
        self.username = username
        self.password = password
        self.connect()

    def connect(self):
        ssh = paramiko.SSHClient()
        # automatically add keys without requiring human intervention
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(self.host, username=self.username, password=self.password)
        tr = ssh.get_transport()
        tr.default_max_packet_size = 100000000
        tr.default_window_size = 100000000
        self.sftp = ssh.open_sftp()
        time.sleep(1)
        print('open connect')

    def close(self):
        self.sftp.close()
        time.sleep(2)
        print('close connect')


    # 下载文件
    @action_try
    def downloadfile(self,remotepath, localpath):
        self.sftp.close()
        self.connect()
        print('开始下载 '+ remotepath)
        try:
            self.sftp.get(remotepath,localpath)
            print('下载文件 ' + remotepath + '成功')
            return '1'
        except:
            print('下载文件 ' + remotepath + '失败')
            if os.path.exists(localpath):
                os.remove(localpath)
            return '0'
        finally:
            self.close()


    # list文件夹
    @action_try
    def listdir(self, remotepath):
        path_list=[]
        list=self.sftp.listdir(remotepath)
        for name in list:
            path_list.append(os.path.join(remotepath,name))
        return path_list

    # 递归遍历得到当前目录下所有的文件路径
    @action_try
    def get_filepaths(self, remotepath,dir_paths=[],file_paths=[]):
        path_list = self.listdir(remotepath)
        for path in path_list:
            #判断是否为文件
            if 'd' not in str(self.sftp.lstat(path)).split()[0]:
                file_paths.append(path)
            #如果为文件夹
            else:
                dir_paths.append(path)
                self.get_filepaths(path,dir_paths,file_paths)
        return  dir_paths,file_paths


    #同步更新sftp,遍历下载文件到本地,同时创建与sftp相同的文件夹目录
    @action_try
    def downloadfilelist(self,remotepath):

        upnumber = 0
        dirslist, fileslist = self.get_filepaths(remotepath)

        all_path = dirslist + fileslist
        uplist = []
        for path in all_path:
            localpath = os.path.join('./test', path.strip('/'))
            if not os.path.exists(localpath):
                uplist.append(localpath)
        print('本次需要更新 ' + str(len(uplist)) + ' 个文件')

        for dir in dirslist:
            #print(dir)
            localpath = os.path.join('./test', dir.strip('/'))
            if not os.path.exists(localpath):
                os.makedirs(localpath)
                upnumber = upnumber + 1
            else:
                pass
                print('目录 ' + dir + ' 已存在,跳过下载')

        for file in fileslist:
            #print(file)
            localpath = os.path.join('./test', file.strip('/'))
            if not os.path.exists(localpath):
                if not os.path.exists(os.path.dirname(localpath)):
                    os.makedirs(os.path.dirname(localpath))
                flag=self.downloadfile(file, localpath)
                #假文件
                # os.mknod(localpath)
                if flag=='1':
                    upnumber = upnumber + 1
            else:
                pass
                print('文件 ' + file + ' 已存在,跳过下载')

        print('************************************')
        print('更新 ' + remotepath + ' 成功')
        print('本次更新了 ' + str(upnumber) + ' 个文件')
        print('************************************')



if __name__=="__main__":
    host = 'xxxx'
    username = 'xxxx'
    password = 'xxxx'
    s=SFTP_obj(host,username,password)

class FTP_obj

#-*- coding:utf-8 -*-
import ftplib
from ftplib import FTP
import traceback
import os

class FTP_obj():

    def action_try(fun):
        def wrapper(*args, **kwargs):  # def 与 return 之后的函数名称一致
            try:
                ret = fun(*args, **kwargs)
                return ret  # return ret 与 ret=func(*args,**kwargs)一致
            except Exception as error:
                print('函数' + fun.__name__ + '操作失败',end='    ')
                print(error)
                #print(traceback.print_exc())
                #print('函数'+fun.__name__+'操作失败')
        return wrapper


    def __init__(self,host,username,password):
        self.ftp = FTP()
        # ftp.set_debuglevel(2)         #打开调试级别2,显示详细信息
        self.ftp.connect(host, 21)  # 连接
        self.ftp.login(username, password)  # 登录,如果匿名登录则用空串代替即可

    # 下载文件
    @action_try
    def downloadfile(self,remotepath, localpath):
        bufsize = 1024  # 设置缓冲块大小
        fp = open(localpath, 'wb')  # 以写模式在本地打开文件
        self.ftp.retrbinary('RETR ' + remotepath, fp.write, bufsize)  # 接收服务器上文件并写入本地文件
        self.ftp.set_debuglevel(0)  # 关闭调试
        print('下载文件' + remotepath + '成功')
        fp.close()  # 关闭文件

    #上传文件
    @action_try
    def uploadfile(self,remotepath, localpath):
        bufsize = 1024
        fp = open(localpath, 'rb')
        self.ftp.storbinary('STOR ' + remotepath, fp, bufsize)  # 上传文件
        self.ftp.set_debuglevel(0)
        print('上传文件' + remotepath + '成功')
        fp.close()

    #删除文件
    @action_try
    def delete(self,remotepath):
        self.ftp.delete(remotepath)
        print('删除文件' + remotepath + '成功')

    #创建文件夹
    def mkdir(self,remotepath):
        self.ftp.mkd(remotepath)
        print('创建文件夹' + remotepath + '成功')

    # 删除文件夹
    @action_try
    def dldir(self, remotepath):
        self.ftp.rmd(remotepath)
        print('删除文件夹' + remotepath + '成功')

    #list文件夹
    @action_try
    def listdir(self, remotepath):
        list = self.ftp.nlst(remotepath)
        return list


    #得到本地需要更新的所有文件路径
    def get_local_paths(self,local,dir_paths=[],file_paths=[]):
        path_list = os.listdir(local)
        for path in path_list:
            path=os.path.join(local,path)
            # 判断是否为文件
            if os.path.isfile(path):
                file_paths.append(path)
            # 如果为文件夹
            else:
                dir_paths.append(path)
                self.get_local_paths(path, dir_paths, file_paths)
        return dir_paths, file_paths

    # 将本地目标文件夹所有内容全部上传ftp
    def upload_all_files(self,local):
        upnumber=0
        dirslist, fileslist = self.get_local_paths(local)

        all_path = dirslist + fileslist
        uplist = []
        for path in all_path:
            print(path)
            ftppath = os.path.join('/XXXX_image/', path.replace('/home/ts/下载/huilin_ftp/',''))
            if self.check(ftppath)=='none':
                uplist.append(ftppath)
        print('本次需要更新 ' + str(len(uplist)) + ' 个文件')
        print(uplist)

        for dir in dirslist:
            #print('****'+dir)
            ftppath = os.path.join('/XXXX_image/', dir.replace('/home/ts/下载/huilin_ftp/',''))
            self.makedirs(ftppath)

        for file in fileslist:
            #print(file)
            ftppath = os.path.join('/XXXX_image/', file.replace('/home/ts/下载/huilin_ftp/',''))
            ftp_dir=os.path.join('/XXXX_image/', os.path.dirname(file).replace('/home/ts/下载/huilin_ftp/',''))
            if self.check(ftppath) != 'file_exists':
                if self.check(ftp_dir)!='dir_exists':
                    self.makedirs(ftp_dir)
                self.uploadfile(ftppath,file)
            else:
                print('文件 '+file+' 已经存在,跳过上传')

    #判断路径类型以及是否存在
    def check(self,path):
        type='none'
        try:
            self.ftp.size(path)
            type='file_exists'
        except:
            try:
                self.ftp.cwd(path)
                type='dir_exists'
            except:
                type='none'
        finally:
            return type

    #递归创建文件夹
    def makedirs(self, path):
        if self.check(path)=='dir_exists':
            print('文件夹 '+path+' 存在,跳过上传')
        else:
            path_split = path.strip('/').split('/')
            dir_path = '/'
            for item in path_split:
                dir_path = dir_path + '/' + item
                if self.check(path)!='dir_exists':
                    try:
                        self.mkdir(dir_path)
                    except:
                        pass




if __name__ == "__main__":
    host='XXXX'
    username='XXXX'
    password='XXXX'
    ftp=FTP_obj(host,username,password)
原文地址:https://www.cnblogs.com/CYHISTW/p/14116030.html