Python FtpLib模塊應(yīng)用操作詳解
本文實(shí)例講述了Python FtpLib模塊應(yīng)用操作。分享給大家供大家參考,具體如下:
Python之FtpLib模塊應(yīng)用
工廠中有這樣的應(yīng)用場(chǎng)景: 需要不間斷地把設(shè)備電腦生成的數(shù)據(jù)文件上傳到遠(yuǎn)程文件存儲(chǔ)服務(wù)器NAS中。
在python自帶的標(biāo)準(zhǔn)庫(kù)中找到ftplib模塊,可以幫助實(shí)現(xiàn)文件的上傳。
場(chǎng)景功能的實(shí)現(xiàn)需要做到以下幾點(diǎn):
- 給定本地路徑,上傳范圍是否包含子文件夾及其文件
- 限定或不限定 哪些文件類型的文件,文件名包含哪些字符串的文件
- 文件上傳后,本地是否要保留
- 掃完一次本地路徑,進(jìn)行下次循環(huán)的間隔周期
- 生成log日志方便查看報(bào)錯(cuò)與已上傳的文件,日志文件保留多久之后要?jiǎng)h除
思路是這樣子,以上內(nèi)容設(shè)計(jì)成一個(gè)config 文件進(jìn)行管控。
1.config.xml文件設(shè)置
<?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 日志保留天數(shù)
- UploadCheck 是否開(kāi)啟上傳
- Loop_Sec 掃描循環(huán)周期
- LocalDirectory 本地路徑,結(jié)尾必須有路徑分隔符
- RemoteDirectory 遠(yuǎn)程路徑,結(jié)尾必須有路徑分隔符
- FileExtension 文件類型,jpg,txt,py,log等等,為*時(shí)不限制文件類型
- FileNameContain 文件名字符串 , 文件名包含哪些字符串的文件,為*時(shí)不限制文件名
- SubDirectoryCheck 子文件夾的文件是否上傳
- SubDirectoryCreateCheck 遠(yuǎn)程路徑是否創(chuàng)建和本地路徑一樣的文件夾
- LocalFileBackupCheck 本地文件是否保留
- FIleCreateTime 掃描本地路徑中創(chuàng)建時(shí)間為多少個(gè)小時(shí)內(nèi)的文件或文件夾
以下是讀取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.相關(guān)邏輯實(shí)現(xiàn)
文件類型及文件名檢驗(yàn)
def checkFileExtension(localfile,extension): ''' 檢查文件名是否符合需要上傳的文件類型 extension為*時(shí),無(wú)文件類型限制上傳 ''' if extension=="*": return True elif localfile.endswith(extension): return True else: return False def checkFileNameContains(localfile,filecontain): ''' 檢查特定文件名的文件 filecontain 為 * 時(shí),不限制上傳文件名 ''' 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))
只上傳創(chuàng)建時(shí)間為N個(gè)小時(shí)內(nèi)的文件或文件夾
def checkFileModifiedTime(localfile,hour): '''只上傳創(chuàng)建時(shí)間為hour小時(shí)內(nèi)的文件''' if os.stat(localfile).st_ctime<time.time()-hour*3600: return False else: return True
生成日志,日志文件保留多久
#創(chuàng)建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)
展開(kāi)子文件夾及相關(guān)判斷邏輯
def listFile(ftp,local,remote,subdircreatecheck,extension,filenamecontains,filecreatetime, localBackupCheck): '''遞歸調(diào)用出子文件或子文件夾 ftp FTP實(shí)例 local 本地文件[夾] remote 遠(yuǎn)程文件[夾] subdircreatecheck 遠(yuǎn)程是否創(chuàng)建對(duì)應(yīng)的子文件夾 extension 文件類型 filecontains 文件名必須包含 filecreatetime 文件修改時(shí)間在多少小時(shí)內(nèi)的 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: #驗(yàn)證ftp遠(yuǎn)程是否已有目錄 ftp.cwd(remote2) #打開(kāi)遠(yuǎn)程目錄,無(wú)法打開(kāi)則報(bào)異常,在異常處理里面創(chuàng)建遠(yuǎn)程目錄 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,subdircreatecheck,extension,filenamecontains, filecreatetime,localBackupCheck) else: if checkFileExtension(local2,extension): if checkFileNameContains(local2,filenamecontains): remote2=remote+'/'+file upload(ftp,local2,remote2) deleteLocalFile(local2,localBackupCheck) except Exception as e: logger.error(e.args[0])
上傳及異常檢驗(yàn)
遠(yuǎn)程文件已存在并且大小與本地一致時(shí)無(wú)需上傳,使用ftp.size()對(duì)比遠(yuǎn)程文件與本地文件大小即可,出現(xiàn)異常表明遠(yuǎn)程文件不存在。
def upload(ftp,localFile,remoteFile): '''以二進(jìn)制形式上傳文件 ftp.size()驗(yàn)證遠(yuǎn)程文件是否存在并且判斷文件大小 ''' 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 # 設(shè)置緩沖器大小 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()
周期循環(huán)
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文件
值的注意的是,64位python環(huán)境下打包的exe不能在32位的Win7、xp運(yùn)行。最后使用32位的python環(huán)境進(jìn)行打包。
pyinstaller -i jftp.ico -F Jftp.py -w
code具體詳情請(qǐng)查看github-jftp
更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python文件與目錄操作技巧匯總》、《Python Socket編程技巧總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》及《Python入門與進(jìn)階經(jīng)典教程》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
相關(guān)文章
Python爬蟲實(shí)例_利用百度地圖API批量獲取城市所有的POI點(diǎn)
下面小編就為大家分享一篇Python爬蟲實(shí)例_利用百度地圖API批量獲取城市所有的POI點(diǎn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01Python根據(jù)歐拉角求旋轉(zhuǎn)矩陣的實(shí)例
今天小編就為大家分享一篇Python根據(jù)歐拉角求旋轉(zhuǎn)矩陣的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-01-01跟老齊學(xué)Python之大話題小函數(shù)(1)
今天本講要講什么呢?今天要介紹幾個(gè)python中的小函數(shù),這幾個(gè)函數(shù)都是從函數(shù)式編程借鑒過(guò)來(lái)的,它們就是:filter、map、reduce、lambda、yield 有了它們,最大的好處是程序更簡(jiǎn)潔2014-10-10如何使用Python做個(gè)自定義動(dòng)態(tài)壁紙
這篇文章主要介紹了如何使用Python做個(gè)自定義動(dòng)態(tài)壁紙的相關(guān)資料,需要的朋友可以參考下方法2021-08-08pandas基礎(chǔ)?Series與Dataframe與numpy對(duì)二進(jìn)制文件輸入輸出
這篇文章主要介紹了pandas基礎(chǔ)Series與Dataframe與numpy對(duì)二進(jìn)制文件輸入輸出,series是一種一維的數(shù)組型對(duì)象,它包含了一個(gè)值序列和一個(gè)數(shù)據(jù)標(biāo)簽2022-07-07Python實(shí)現(xiàn)for循環(huán)倒序遍歷列表
這篇文章主要介紹了Python實(shí)現(xiàn)for循環(huán)倒序遍歷列表,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05django-rest-swagger的優(yōu)化使用方法
今天小編就為大家分享一篇django-rest-swagger的優(yōu)化使用方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08Python 訪問(wèn)限制 private public的詳細(xì)介紹
在一個(gè)模塊中,我們可能會(huì)定義很多函數(shù)和變量。這篇文章主要介紹了Python 訪問(wèn)限制 private public的詳細(xì)介紹,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10python 進(jìn)程 進(jìn)程池 進(jìn)程間通信實(shí)現(xiàn)解析
這篇文章主要介紹了python 進(jìn)程 進(jìn)程池 進(jìn)程間通信實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08