python项目运行过程中定期更新sftp服务器文件到本地

从sftp服务器下载文件到本地,这是一个简单的需求,使用paramkio模块就可以实现,那么如何在项目运行过程中定期从sftp端拉下来要更新的项目文件,并且更新到项目中。

从sftp服务器下载文件到本地

将sftp服务器的文件下载到本地临时创建的文件夹:

import paramiko
class UpdateFile:
    def __init__(self,host,username,password,port=22):
        self.sf = paramiko.Transport((host,port))  #连接服务器
        self.sf.connect(username=username,password=password)  # 登录
        self.sftp = paramiko.SFTPClient.from_transport(self.sf)  #创建操作对象

    def isDir(self,sftp,path):  # 判断远程的文件对象是目录还是文件
        try:
            sftp.chdir(path)  #尝试进入下一级
            sftp.chdir('..')
            return True
        except:
            return False

    def downloadDir(self,downDir,remoteDir):  # 下载文件到本地
        if not os.path.isdir(downDir):  #先判断本地临时文件夹是否存在
            os.makedirs(downDir)
        self.sftp.chdir(remoteDir)  #进入远程目录
        remote_files = self.sftp.listdir()  #查看当前远程目录下的所有文件
        for r_f in remote_files:
            downpath = os.path.join(downDir,r_f)  #拼接好本地要保存的路径
            if r_f in ['__pycache__', '.idea','.svn',os.path.basename(__file__)]:  #不去下载的文件
                pass
            else:
                if not os.path.exists(downpath):  #先判断本地目录是否存在
                    if self.isDir(self.sftp, r_f):   #再判断当前对象在远程是否为目录
                        os.makedirs(downpath)   #如果远程是目录,则在本地创建对应的目录
                        self.downloadDir(downpath, r_f)  #同时下载该目录下的所有文件
                    else:
                        open(downpath,'wb')   #如果不是目录,则创建文件
                        self.sftp.get(r_f, downpath)  #同时将文件下载到本地路径中
                else:  #本地对应目录已存在,则直接下载
                    if self.isDir(self.sftp, r_f): 
                        self.downloadDir(downpath, r_f)
                    else:
                        self.sftp.get(r_f, downpath)
        self.sftp.chdir('..')
        return True

将下载的文件更新到本地对应的文件中

采用深度遍历的方法,从临时文件夹中将从sftp下载的文件依次更新到项目中:

def updateFiles(localDir,downDir):  # 更新文件
    stack = []  #创建栈
    stack.append(downDir)  #将下载的文件路径压入栈中,准备遍历
    while True:
        if len(stack) == 0:
            shutil.rmtree(os.path.abspath('.') + r'\backup')  # 表示更新完成,栈中已经没有内容,则删除备份文件夹
            return True
        dir_ = stack.pop()
        ds = os.listdir(dir_)
        for dname in ds:
            dpath = os.path.join(dir_,dname)  # 下载下来的文件路径
            # backup在这里是我们设置的临时文件夹,我们要从其后匹配出本地项目中有的路径,与本地路径拼接
            relative_path = re.compile(r'.+\\backup(.+)').findall(dpath)[0]
            wpath = localDir+relative_path  # 要更新的文件路径
            if os.path.isdir(dpath):
                if not os.path.exists(wpath):
                    os.makedirs(wpath)
                stack.append(dpath)  # 是目录则加入栈中
            else:
                try:
                     #打开本地文件同时读取下载的文件写入到本地文件,这一步不能分开执行,否则会造成文件丢失
                    open(wpath,'wb').write(open(dpath, 'rb').read())  
                except Exception as e:
                    print(e)
                    return False

在项目运行中更新文件

这里将调用更新放在了后台定时任务中,设定情景:定期请求中心服务器获取当前项目的最新版本号和sftp服务器地址信息,本地config文件中配有当前项目的版本号,进行对比,如果版本不同,则去从sftp服务器下载文件更新到项目中,同时更新本地版本号。这里只写了任务,任务添加到任务对象中就不写了:

impot config
Now_ver = config.VER
def updateVer(self):
    r = requests.get(url_updatefile, timeout=TIMEOUT)
    res_dict = json.loads(r.text)
    print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '获取项目文件最新版本...')

    if res_dict['status'] == 0:
        new_ver = res_dict['data']['version']
        ftp = res_dict['data']['ftp']
        # 将本地版本号与远程版本号对比
        if int(new_ver) == int(Now_ver):  # 已经是最新版本
            pass
        else:
            try:
                #从中心服务器请求到的sftp是链接形式的:sftp://user:passwd@host:port/远程地址
                regex = re.compile(r'sftp://(\w+):(\w+)@(.*?):(\d+)/(.*)')  #使用正则提取关键信息
                m_s = regex.findall(ftp)
                print(m_s)
                username, password, host, port, remoteDir = m_s[0]
                f = UpdateFile(host, username, password, int(port))  #链接sftp
                downtag = f.downloadDir(os.path.abspath('.')+r'\backup', '/'+remoteDir)  #下载文件到本地临时文件夹
                if downtag:  #如果下载完成,则将临时文件夹中的内容更新到项目中
                    updatetag = updateFiles(os.path.abspath('.'), os.path.abspath('.')+r'\backup')
                    if updatetag:  #如果项目也更新成功,则将最新版本号写入到config文件中
                        # 更新版本号
                        with open('config.py', 'r+',encoding='utf-8') as s:
                            lines = s.readlines()
                            s.seek(0, 0)
                            for line in lines:
                                line_new = line.replace('VER = '+str(Now_ver), 'VER = '+new_ver)
                                s.write(line_new)
                        # time.sleep(2)
                        # os.system('../reload.bat')
                    else:
                        pass
                else:
                    pass
            except Exception as e:
                print(e)
                ext.writelog('更新文件出错!')

以上就是完整的在项目运行过程中定期从sftp下载有更新的文件,并将更新的文件同步到本地项目中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值