Python FtpLib模組應用操作詳解
阿新 • • 發佈:2020-01-09
本文例項講述了Python FtpLib模組應用操作。分享給大家供大家參考,具體如下:
Python之FtpLib模組應用
工廠中有這樣的應用場景: 需要不間斷地把裝置電腦生成的資料檔案上傳到遠端檔案儲存伺服器NAS中。
在python自帶的標準庫中找到ftplib模組,可以幫助實現檔案的上傳。
場景功能的實現需要做到以下幾點:
- 給定本地路徑,上傳範圍是否包含子資料夾及其檔案
- 限定或不限定 哪些檔案型別的檔案,檔名包含哪些字串的檔案
- 檔案上傳後,本地是否要保留
- 掃完一次本地路徑,進行下次迴圈的間隔週期
- 生成log日誌方便檢視報錯與已上傳的檔案,日誌檔案保留多久之後要刪除
思路是這樣子,以上內容設計成一個config 檔案進行管控。
1.config.xml檔案設定
<?xml version="1.0"?> <Config> <ServerIP>10.16.xx.xx</ServerIP> <UserID>cc</UserID> <Passwd>xxx</Passwd> <LogBackupDay>10</LogBackupDay> <UploadCheck>TRUE</UploadCheck> <Loop_Sec>30</Loop_Sec> <LocalDirectory>C:\Users\Administrator\Desktop\TEST\</LocalDirectory> <RemoteDirectory>/DATA/AOI/T1TEST200/</RemoteDirectory> <FileExtension>csv</FileExtension> <FileNameContain>*</FileNameContain> <SubDirectoryCheck>TRUE</SubDirectoryCheck> <SubDirectoryCreateCheck>FALSE</SubDirectoryCreateCheck> <LocalFileBackupCheck>TRUE</LocalFileBackupCheck> <FileCreateTime>80</FileCreateTime> </Config>
- LogBackupDay 日誌保留天數
- UploadCheck 是否開啟上傳
- Loop_Sec 掃描迴圈週期
- LocalDirectory 本地路徑,結尾必須有路徑分隔符
- RemoteDirectory 遠端路徑,結尾必須有路徑分隔符
- FileExtension 檔案型別,jpg,txt,py,log等等,為*時不限制檔案型別
- FileNameContain 檔名字串 , 檔名包含哪些字串的檔案,為*時不限制檔名
- SubDirectoryCheck 子資料夾的檔案是否上傳
- SubDirectoryCreateCheck 遠端路徑是否建立和本地路徑一樣的資料夾
- LocalFileBackupCheck 本地檔案是否保留
- FIleCreateTime 掃描本地路徑中建立時間為多少個小時內的檔案或資料夾
以下是讀取config.xml的程式碼
from xml.dom.minidom import parse def readConfig(): '''讀取上傳配置''' conf=parse(os.getcwd()+os.sep+'config.xml');#config檔案與程式放在同一目錄 host=conf.getElementsByTagName("ServerIP")[0].firstChild.data username =conf.getElementsByTagName("UserID")[0].firstChild.data passwd=conf.getElementsByTagName("Passwd")[0].firstChild.data logBackupDay=int(conf.getElementsByTagName("LogBackupDay")[0].firstChild.data) uploadCheck=conf.getElementsByTagName("UploadCheck")[0].firstChild.data uploadLoopTime=int(conf.getElementsByTagName("Loop_Sec")[0].firstChild.data) localDir=conf.getElementsByTagName("LocalDirectory")[0].firstChild.data remoteDir=conf.getElementsByTagName("RemoteDirectory")[0].firstChild.data fileExtension=conf.getElementsByTagName("FileExtension")[0].firstChild.data fileNameContain=conf.getElementsByTagName("TxtFileNameContain")[0].firstChild.data subDirCheck=conf.getElementsByTagName("SubDirectoryCheck")[0].firstChild.data subDirCreateCheck=conf.getElementsByTagName("SubDirectoryCreateCheck")[0].firstChild.data backupCheck=conf.getElementsByTagName("LocalFileBackupCheck")[0].firstChild.data fileCreateTime=int(conf.getElementsByTagName("FileCreateTime")[0].firstChild.data) conflist=[host,username,passwd,logBackupDay,uploadCheck,uploadLoopTime,localDir,remoteDir,fileExtension,fileNameContain,subDirCheck,subDirCreateCheck,backupCheck,fileCreateTime] return conflist
2.相關邏輯實現
檔案型別及檔名檢驗
def checkFileExtension(localfile,extension): ''' 檢查檔名是否符合需要上傳的檔案型別 extension為*時,無檔案型別限制上傳 ''' if extension=="*": return True elif localfile.endswith(extension): return True else: return False def checkFileNameContains(localfile,filecontain): ''' 檢查特定檔名的檔案 filecontain 為 * 時,不限制上傳檔名 ''' if filecontain=="*": return True elif filecontain in localfile: return True else: return False
檔案上傳之後,本地是否保留
def deleteLocalFile(deleteCheck,localfile): if not deleteCheck: os.remove(localfile) logger.info("Remove local file:{}".format(localfile))
只上傳建立時間為N個小時內的檔案或資料夾
def checkFileModifiedTime(localfile,hour): '''只上傳建立時間為hour小時內的檔案''' if os.stat(localfile).st_ctime<time.time()-hour*3600: return False else: return True
生成日誌,日誌檔案保留多久
#建立logger日誌 logger = logging.getLogger() logger.setLevel(logging.INFO) #filehandler rq = time.strftime('%Y%m%d',time.localtime(time.time())) log_path = os.getcwd()+os.sep + 'Logs'+os.sep if not os.path.exists(log_path): os.mkdir(log_path) log_name = log_path + rq + '.log' logfile = log_name fh = logging.FileHandler(logfile,mode='w') fh.setLevel(logging.DEBUG) #filehandler輸出格式 formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s") fh.setFormatter(formatter) logger.addHandler(fh)
def deleteLog(days): '''刪除多少天之前的日誌檔案''' for file2 in os.listdir(log_path): logfile=os.path.join(log_path,file2) if os.stat(logfile).st_ctime<time.time()-days*24*3600: os.remove(logfile)
展開子資料夾及相關判斷邏輯
def listFile(ftp,local,remote,subdircreatecheck,extension,filenamecontains,filecreatetime,localBackupCheck): '''遞迴調用出子檔案或子資料夾 ftp FTP例項 local 本地檔案[夾] remote 遠端檔案[夾] subdircreatecheck 遠端是否建立對應的子資料夾 extension 檔案型別 filecontains 檔名必須包含 filecreatetime 檔案修改時間在多少小時內的 localBackupCheck 本地檔案是否保留 ''' for file in os.listdir(local): local2=os.path.join(local,file) #路徑+檔名為 完整路徑 remote2=remote+'/'+file try: if not checkFileModifiedTime(local2,filecreatetime): continue if not subdircreatecheck: remote2=remote if os.path.isdir(local2): try: #驗證ftp遠端是否已有目錄 ftp.cwd(remote2) #開啟遠端目錄,無法開啟則報異常,在異常處理裡面建立遠端目錄 except Exception as e: logger.error("Fail to open directory.") logger.info("Open directory: {} fail,so create dir.".format(remote2)) ftp.mkd(remote2) logger.info("ItslocalDir:{}".format(local2)) listFile(ftp,local2,remote2,localBackupCheck) else: if checkFileExtension(local2,extension): if checkFileNameContains(local2,filenamecontains): remote2=remote+'/'+file upload(ftp,remote2) deleteLocalFile(local2,localBackupCheck) except Exception as e: logger.error(e.args[0])
上傳及異常檢驗
遠端檔案已存在並且大小與本地一致時無需上傳,使用ftp.size()對比遠端檔案與本地檔案大小即可,出現異常表明遠端檔案不存在。
def upload(ftp,localFile,remoteFile): '''以二進位制形式上傳檔案 ftp.size()驗證遠端檔案是否存在並且判斷檔案大小 ''' try: if ftp.size(remoteFile)==os.path.getsize(localFile): return except ftplib.error_perm as err: logger.warning("{0}.When upload file:{1}".format(err.args[0],remoteFile)) except Exception as e: logger.warning("other error!") uf = open(localFile,'rb') bufsize = 1024 # 設定緩衝器大小 try: ftp.storbinary('STOR ' + remoteFile,uf,bufsize) logger.info("File has upload success:{}".format(remoteFile)) except: logger.error("File Upload Fail!:{}".format(remoteFile)) finally: uf.close()
週期迴圈
logger.info("File Send Program Start!") while uploadCheck: logger.info("File Send Program LoopStart!") deleteLog(logBackupDay) f=ftplib.FTP(host) try: ### except: ### finally: f.quit() logger.info("Loop end,wait for next loop!") time.sleep(loopTime)
3.打包exe檔案
pyinstaller庫打包
值的注意的是,64位python環境下打包的exe不能在32位的Win7、xp執行。最後使用32位的python環境進行打包。
pyinstaller -i jftp.ico -F Jftp.py -w
code具體詳情請檢視github-jftp
更多關於Python相關內容感興趣的讀者可檢視本站專題:《Python檔案與目錄操作技巧彙總》、《Python Socket程式設計技巧總結》、《Python資料結構與演算法教程》、《Python函式使用技巧總結》、《Python字串操作技巧彙總》及《Python入門與進階經典教程》
希望本文所述對大家Python程式設計有所幫助。