zoukankan      html  css  js  c++  java
  • python脚本---上传本机文件到远端(接上文)

    上一个脚本刚写完,第二天不用了。。。需要传到linux服务器上。。。
    So,下一个脚本开始:

    1. 这次选择用的paramiko模块

    pip install paramiko

    2. 整体思路

    • 遍历本地目录放入集合
    • 读取上次上传到linux的文件信息(existsfile.log)放入另一个集合
    • 两个集合取补集(好像叫对称差集吧)
    • 上传补集内的文件

    远程目录必须存在,put方法的远程目录才有效。而且必须是文件的绝对路径,不能是文件夹路径,否则也会失败;mkdir方法一样,不可以递归地创建目录,在这两个地方坑了好久。

    3. 代码实现

    syncfiles.py

    
    # -*- coding: utf-8 -*-
    __author__ = "hand"
    
    import os
    import paramiko
    import settings
    import platform
    from datetime import datetime
    
    
    class SyncFiles(object):
        """
        复制本机文件到远端
        """
        def __init__(self):
            self.f = open("existsfile.log", "a+")
            self.remote_host = settings.REMOTE_HOST
            self.remote_port = settings.REMOTE_PORT
            self.remote_user = settings.REMOTE_USER
            self.remote_pwd = settings.REMOTE_PWD
            if settings.REMOTE_PATH[-1] == '/' or settings.REMOTE_PATH[-1] == '\':
                self.remote_path = settings.REMOTE_PATH[0:-1]
            else:
                self.remote_path = settings.REMOTE_PATH
            if settings.LOCAL_PATH[-1] == '/' or settings.LOCAL_PATH[-1] == '\':
                self.local_path = settings.LOCAL_PATH[0:-1]
            else:
                self.local_path = settings.LOCAL_PATH
    
        def get_upload_files(self):
            """获取待上传的所有文件"""
            local_path_set = set()  # 本地文件
            file_transfered_set =set()  # 已经上传过的文件
            for root, dirs, files in os.walk(self.local_path):
                for file in files:
                    local_file = os.path.join(root, file)  # 完整的文件路径:/A/B/C/1.txt
    
                    local_path_set.add(local_file)
    
            self.f.seek(0,0)  # 将记录文件指针放在文件头,用于读文件
    
            for line in self.f.readlines():
                file_transfered = line.split("-")[-1].strip()
    
                file_transfered_set.add(file_transfered)
    
            ready_upload_set = local_path_set ^ file_transfered_set  # 待上传的文件
            return list(ready_upload_set)
    
        def record_log(self, path):
    
            now = datetime.now()
            # if platform.platform().startswith("Windows"):
            # self.f.write(now.strftime('%Y/%M/%d %H:%M:%S %A ') + ' -  ' + path + '\r\n')
            # else:
            self.f.write(now.strftime('%Y/%M/%d %H:%M:%S %A ') + ' -  ' + path + '
    ')
    
        def transfile(self):
            """上传文件"""
            try:
                # 实例化Transport
                trans = paramiko.Transport((self.remote_host, 22))
                # 建立连接
                trans.connect(username=self.remote_user, password=self.remote_pwd)
                # 实例化一个sftp对象
                sftp = paramiko.SFTPClient.from_transport(trans)
    
                ready_upload_list = self.get_upload_files()
    
                already_dir = []  # 存放远端新建的目录
                if ready_upload_list:
    
                    for local_file_path in ready_upload_list:
    
                        if platform.platform().startswith("Windows"):
    
                            file_need = local_file_path.replace(self.local_path, '').replace('\','/')  # 取出本地路径后,需要同步到远端的部分:B/C/1.txt
    
                        else:
                            file_need = local_file_path.replace(self.local_path, '')
                        remote_file_path = self.remote_path + file_need
    
                        try:
                            # 上传文件,必须是文件的完整路径,远端的目录必须已经存在
                            sftp.put(localpath=local_file_path, remotepath=remote_file_path)
                            self.record_log(local_file_path)
                        except Exception as e:
                            # 如果目录不存在就创建,但是不支持递归创建
    
                            dir_need_list = os.path.split(file_need)[0].split("/")  # B、C
                            dir1 = ''
                            print dir_need_list
                            for dir in dir_need_list[1:]:
                                if dir not in already_dir:
                                    # 目录存在会报错,所以把新建过的目录存在一个全局列表中
                                    if platform.platform().startswith("Windows"):
                                        sftp.mkdir(os.path.join(self.remote_path, dir1, dir).replace('\','/'))
                                    else:
                                       sftp.mkdir(os.path.join(self.remote_path, dir1, dir))
                                dir1 = dir
                                already_dir.append(dir)  # 新建过的目录存在一个全局列表中
                                # 再次执行
                            sftp.put(localpath=local_file_path, remotepath=remote_file_path)
                            self.record_log(local_file_path)
            except Exception as e:
                pass
            finally:
                trans.close()
    
    if __name__ == "__main__":
        sf = SyncFiles()
        sf.transfile()
    

    settings.py

    # -*- coding: utf-8 -*-
    __author__ = "hand"
    
    REMOTE_HOST = 'X.X.X.X'
    REMOTE_PORT = 22
    REMOTE_USER = '用户名'
    REMOTE_PWD = '密码'
    REMOTE_PATH = '/storage/zhaoning/ttt'
    LOCAL_PATH = '/Users/smallcaff/Desktop/filetest'

    4. 参考

    看过其他一些人的代码,也拉下来测试过,有的好像在创建远端目录时有问题,不知道跟版本有关系没
    这篇博客关于paramiko用法写的很详细,paramiko用法没有看官方教程,参考了这个:python模块之 paramiko

  • 相关阅读:
    590. N 叉树的后序遍历
    CF605E
    网络流水题题单
    wqs二分的边界
    luoguP6326 Shopping
    【THUWC2020】工资分配
    CF1336简要题解
    「PKUWC2020」最小割
    洛谷P4895 独钓寒江雪
    省选联考2020简要题解
  • 原文地址:https://www.cnblogs.com/SmallCaff/p/10650698.html
Copyright © 2011-2022 走看看