Use paramiko, tkinter, os and other modules to realize remote connection to sftp, and perform recursive timing transmission of folders

author == ‘ljh’

from tkinter import *

Make GUI interface

import paramiko

for remote

import time
from tqdm import tqdm

to show the process

import os
import threading

The plan is to call multi-threading to complete the update file to achieve faster speed. But in this case, you need to divide the run function into multiple functions. If the number is large, you can consider it yourself

class Application(Frame):
def init (self, master):
super(Application, self). init (master)
# Inherit the initialization of super class/parent class

    Label(self, text='Remote Data Dir').grid(row=0, column=0, sticky=W, padx=0, pady=0)
    default_remote_dir = StringVar()
    # 字符变量
    default_remote_dir.set(r'/备站备份/')
    self.remote_dir_ent = Entry(self, textvariable=default_remote_dir, width=52)
    # width值是自己摸索的 grid()来布局需要自己重复的实验,以求找到最合适的大小
    self.remote_dir_ent.grid(row=0, column=1, columnspan=3, sticky=W, padx=0, pady=0)

    Label(self, text='Local Data Dir').grid(row=1, column=0, sticky=W, padx=0, pady=0)
    default_local_dir = StringVar()
    default_local_dir.set(r'D:\ljh\untitled\sdv')
    self.local_dir_ent = Entry(self, textvariable=default_local_dir, width=52)
    self.local_dir_ent.grid(row=1, column=1, columnspan=3, sticky=W, padx=0, pady=0)

    Label(self, text='Remote IP').grid(row=2, column=0, sticky=W, padx=0, pady=0)
    default_ip = StringVar()
    default_ip.set('10.127.84.11')
    self.ip_ent = Entry(self, textvariable=default_ip)
    self.ip_ent.grid(row=2, column=1, sticky=W, padx=0, pady=0)

    Label(self, text='Remote Port').grid(row=2, column=2, sticky=W, padx=0, pady=0)
    default_port = IntVar()
    default_port.set(22)
    self.port_ent = Entry(self, textvariable=default_port)
    self.port_ent.grid(row=2, column=3, padx=0, pady=0)

    Label(self, text='Username').grid(row=3, column=0, sticky=W, padx=0, pady=0)
    default_username = StringVar()
    default_username.set('Backup')
    self.username_ent = Entry(self, textvariable=default_username)
    self.username_ent.grid(row=3, column=1, sticky=W, padx=0, pady=0)

    Label(self, text='Password').grid(row=3, column=2, sticky=W, padx=0, pady=0)
    default_password = StringVar()
    default_password.set('re955426')
    self.password_ent = Entry(self, textvariable=default_password, show='*')
    self.password_ent.grid(row=3, column=3, padx=0, pady=0)

    Label(self, text='time interval(h)').grid(row=4, column=0, sticky=W, padx=0, pady=0)
    default_time_interval = IntVar()
    default_time_interval.set(24)
    self.time_interval_ent = Entry(self, textvariable=default_time_interval)
    self.time_interval_ent.grid(row=4, column=1, sticky=W, padx=0, pady=0)

    self.bttn = Button(self, text='Start ', command=self.run)
    self.bttn.grid(row=5, rowspan=2, column=0, columnspan=2, sticky=W, padx=0, pady=0)

    # 原本打算做出一个显示更新信息的文本,但不会异步更新。因此先放到一边
    # self.txt = Text(self, wrap=WORD)
    # self.txt.grid(row=5, rowspan=2, column=0, columnspan=4, padx=0, pady=0)
    # self.scroll = Scrollbar(self, command=self.txt.yview, width=15)
    # self.txt.configure(yscrollcommand=self.scroll.set)
    # self.scroll.grid(row=5, rowspan=2, column=5, sticky=N+S)
    self.grid()

def run(self):
    ip = self.ip_ent.get()
    port = self.port_ent.get()
    port = int(port)
    username = self.username_ent.get()
    password = self.password_ent.get()
    # 以上得到GUI中Entry中的输入值
    transport = paramiko.Transport((ip, port))
    transport.connect(username=username, password=password)
    sftp = paramiko.SFTPClient.from_transport(transport)
    # 连接远程sftp,并实例化一个远程会话
    remote_source_dir = self.remote_dir_ent.get()
    local_source_dir = self.local_dir_ent.get()
    print('Running Update time: ' + str(time.ctime()))
    while True:
        # 用来定时更新,所以用的死循环
        local_walks = os.walk(local_source_dir)
        # 考虑到文件夹的递归问题即文件夹里还有文件夹,因此调用os.walk()a方法, 其返回一个迭代器,3维数组,第一个为
        # 当前的目录,第二个为当前路径下的目录,第三个为当前目录下的文件名
        year = time.localtime()[0]
        month = time.localtime()[1]
        day = time.localtime()[2]
        today_files = '{:4}{:02}{:02}'.format(year, month, day)
        # 此处构造了一个有关当天时间的字符串,因为我这边是不要更新今天生成的不完整的文件的
        # (文件在第二天会在此有其他软件生成),这里的思想是构造你需要过滤的文件,在一次更新中不更新此类文件

        local_walks = list(local_walks)
        # 将迭代器变为列表,因为需要循环调用
        for i in local_walks:
            local_dirname = i[0]
            dirs = i[1]
            files = i[2]
            # 此处的local_dirname、dirs、files就是上述os.walk()返回的3维数组的内容
            dirname = i[0].replace(local_source_dir, '')
            dirname = dirname.replace('\\', '')
            # 此处得到递归的文件夹的名字,方便与远程的服务器中的地址构成新的目录,从而传输文件
            if dirname != '':
                remote_dirname = remote_source_dir + dirname + '/'
            else:
                remote_dirname = remote_source_dir + dirname
            # 得到新的远程目录
            for t in range(1):
                try:
                    sftp.mkdir(remote_dirname)
                    print('Create remote dir:  ' + remote_dirname + '!')
                except:
                    continue
            # 检查是否需要新建文件夹,因为sftp中我没有看到类似于os.path.isdir()的方法,因此考虑用try来解决
            # for循环是为了配合continue

            remote_source_dirs = sftp.listdir(remote_dirname)
            # 得到远程服务器下当前目录下的文件和目录列表
            transport_files = set(files) - set(remote_source_dirs)
            transport_files = list(transport_files)
            # 利用集合的相减得到要更新的文件。注意此处是单纯的文件。


            for j in transport_files:
                if today_files in j:
                    transport_files.remove(j)
                elif j in dirs:
                    transport_files.remove(j)
            # 此处为过滤不需要更新的文件,elif部分可以考虑不要
            for j in tqdm(transport_files, bar_format='{l_bar}{bar}'):
                # 方法tqdm可以显示更新的进度
                file_path = local_dirname + '\\' + str(j)
                remote_file_path = remote_dirname + str(j)
                # 构造本地和远程的文件的路径
                sftp.put(file_path, remote_file_path)
                # 将文件从本地上传到服务器

            print('Remote directory: ' + remote_dirname + '\'s  updating is completed!')

        interval = self.time_interval_ent.get()
        interval = int(interval)
        # get()得到的是字符串,因此强制转换成整型
        time.sleep(interval // 4)
        # 设置休眠时间
        print('Running Update time: ' + str(time.ctime()))

if name == ‘main‘:
root = Tk()
root.title(‘SFTP_数据备份’)
root.geometry(‘475x160’)
app = Application(root)
root.mainloop()

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324808475&siteId=291194637
Recommended