1. 程式人生 > 實用技巧 >python sftp ftp 造輪子,實現多個方法

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)