python腳本---上傳本機文件到遠端(接上文)

上一個腳本剛寫完,第二天不用了。。。需要傳到linux服務(wù)器上。。。
So,下一個腳本開始:

1. 這次選擇用的paramiko模塊

pip install paramiko

2. 整體思路

  • 遍歷本地目錄放入集合
  • 讀取上次上傳到linux的文件信息(existsfile.log)放入另一個集合
  • 兩個集合取補集(好像叫對稱差集吧)
  • 上傳補集內(nèi)的文件

遠程目錄必須存在,put方法的遠程目錄才有效。而且必須是文件的絕對路徑,不能是文件夾路徑,否則也會失??;mkdir方法一樣,不可以遞歸地創(chuàng)建目錄,在這兩個地方坑了好久。

3. 代碼實現(xiàn)

syncfiles.py


# -*- coding: utf-8 -*-
__author__ = "hand"

import os
import paramiko
import settings
import platform
from datetime import datetime


class SyncFiles(object):
    """
    復(fù)制本機文件到遠端
    """
    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()  # 已經(jīng)上傳過的文件
        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 + '\n')

    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:
                        # 上傳文件,必須是文件的完整路徑,遠端的目錄必須已經(jīng)存在
                        sftp.put(localpath=local_file_path, remotepath=remote_file_path)
                        self.record_log(local_file_path)
                    except Exception as e:
                        # 如果目錄不存在就創(chuàng)建,但是不支持遞歸創(chuàng)建
                        
                        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)  # 新建過的目錄存在一個全局列表中
                            # 再次執(zhí)行
                        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. 參考

看過其他一些人的代碼,也拉下來測試過,有的好像在創(chuàng)建遠端目錄時有問題,不知道跟版本有關(guān)系沒
這篇博客關(guān)于paramiko用法寫的很詳細,paramiko用法沒有看官方教程,參考了這個:python模塊之 paramiko

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容