Python 代碼最佳化實踐

來源:互聯網
上載者:User

標籤:提取   %s   參數檔案   pytho   業務   目標軟體   特定   return   記錄   

最近在用Python寫一個一鍵替換檔案的指令檔,大概的功能是,向程式傳遞一個本地或SFTP目錄的參數,程式可以把指定目錄所有檔案替換到特定應用程式的對應目錄。程式提供了如下2種命令列調用:

Usage: demo.py [sourcedir]
Usage: demo.py [sourcedir] bydir

第一種調用的實際操作是:讀取特定應用程式目錄所有檔案,並擷取全路徑作為一個集合,再把參數檔案夾中檔案按檔案名稱與集合中檔案進行匹配,如果匹配上則執行替換操作。

第二種調用的實際操作是:按參數檔案夾的目錄存放的路徑,完整替換到應用程式的對應目錄。

下面是最初的代碼實現:

#執行本地檔案替換的具體操作 def ReplaceLocalFiles(filepath, context, filecontext, softpath, bydir):    if (":" not in filepath) or (not os.path.isdir(filepath)):        printandwritelog(u"目標路徑有誤,請確認是目錄後再重試")        return "error"    fileList = os.walk(filepath)    for root, dirs, files in fileList:        for file in files:            if bydir:#如果按目錄進行替換的話走下面這個邏輯分支                filefullpath = os.path.join(root, file)                targetfullpath = filefullpath.replace(filepath, softpath)                shutil.copy2(filefullpath, targetfullpath)                printandwritelog(u"檔案 %s 拷貝到 %s 成功" % (filefullpath, targetfullpath))            else:#如果自行尋找檔案路徑進行替換的話先走下這個邏輯分支                filecounts = checkcount(file, filecontext)                if (0 == filecounts):                    printandwritelog(u"沒有找到檔案%s的路徑,請使用指定路徑方式進行替換" % file)                    continue                elif (1 < filecounts):                    printandwritelog(u"檔案 %s 有 %s 個路徑,請使用指定路徑方式進行替換" % (file , filecounts))                    continue                elif (1 == filecounts):                    for line in context.split("\n"):                        filename = line.split("\\")[-1]                        if file == filename:                            os.rename(line , line + str(random.randint(0, 100)))                            shutil.copy2(os.path.join(root, file), line)                            printandwritelog(u"檔案 %s 拷貝到 %s 成功" % (os.path.join(root, file), line))                else:                    printandwritelog(u"替換檔案個數有誤%s" % file)#判斷如果是本地檔案則直接調用替換函數,如果是網路路徑,則先下載檔案再替換def RelpaceFiles(filepath, context, filecontext, softpath, bydir):    if ":" in filepath:        printandwritelog(u"提供的本地路徑,走本地路徑檔案替換流程")        ReplaceLocalFiles(filepath, context, filecontext, softpath, bydir)    else:        printandwritelog(u"提供的FTP路徑,先下載檔案到本地後再執行替換流程")        sourceFileDir = cur_file_dir() + r"\testdir"        if os.path.isdir(sourceFileDir):            shutil.rmtree(sourceFileDir)        obj = netutilex.SFTP("192.168.1.100", "test", "testpwd")        obj.syncSftpDir(filepath, sourceFileDir)        obj.close()        ReplaceLocalFiles(sourceFileDir, context, filecontext, softpath, bydir)#先處理替換前的前置操作,環境準備好之後執行替換操作    def ReplaceAllFiles(filepath, bydir):    softpath = checkinst()    if ("notinst" == softpath):        printandwritelog(u"沒有檢測到衛士安裝目錄,請確認後重試")        return "error"    else:        context, filecontext = getallfiles(softpath)        RelpaceFiles(filepath, context, filecontext, softpath, bydir)

先簡單說明下各函數的功能:

ReplaceLocalFiles:主要功能函數,實現具體的替換操作;
RelpaceFiles:根據傳入參數判斷是否是網路路徑,如果是則先把檔案下載到本地,然後調用ReplaceLocalFiles執行替換操作;
ReplaceAllFiles:做了一些環境準備的事情,然後調用實際的功能函數RelpaceFiles進行幹活;
printandwritelog:記錄日誌並輸出;
checkinst:檢查目標程式是否安裝,如果安裝則返回安裝路徑;
getallfiles:擷取目標應用程式的檔案全路徑集合;
checkcount:擷取指定檔案名稱在目標應用程式檔案集合中出現的次數
netutilex:一個獨立的操作SFTP的庫檔案。

從目前的代碼中能發現至少有2個地方可以最佳化:

  1. 函數之間需要傳遞的參數太多了,可以看看是否全部必要,考慮下如何精簡;
  2. 部分商務邏輯太細化,有重複的代碼實現,導致實現看起來比較臃腫。

對於第1點,最佳化的思路是:對於非所有函數都必須調用的參數,儘可能的固化到實際使用的函數中,避免各函數僅僅做了傳遞員的工作。

對於第2點,最佳化的思路是:合并同類項,對於重複代碼的部分,儘可能提取到共用邏輯中實現。

下面是最佳化後的代碼:

#執行本地檔案替換的具體操作      def ReplaceLocalFiles(filepath, bydir):    if (":" not in filepath) or (not os.path.isdir(filepath)):        printandwritelog(u"目標路徑有誤,請確認是合法目錄後重試")        return "error"    softpath = checkinst()    if ("notinst" == softpath):        printandwritelog(u"沒有擷取到目標軟體安裝目錄,請確認後重試")        return "error"    context, filecontext = getallfiles(softpath)    fileList = os.walk(filepath)    for root, dirs, files in fileList:        for file in files:            filefullpath = os.path.join(root, file)            targetfullpath = filefullpath.replace(filepath, softpath)            if not bydir:#如果自行尋找檔案路徑進行替換的話先走下這個邏輯分支                filecounts = checkcount(file, filecontext)                if (0 == filecounts):                    printandwritelog(u"沒有找到檔案%s的路徑,請使用指定路徑方式進行替換" % file)                    continue                elif (1 < filecounts):                    printandwritelog(u"檔案 %s 有 %s 個路徑,請使用指定路徑方式進行替換" % (file , filecounts))                    continue                elif (1 == filecounts):                    for line in context.split("\n"):                        filename = line.split("\\")[-1]                        if file == filename:                            targetfullpath = line                else:                    printandwritelog(u"替換檔案個數有誤%s" % file)            if os.path.isfile(targetfullpath):                randomend = random.randint(0, 100)                os.rename(targetfullpath , targetfullpath + str(randomend))            shutil.copy2(filefullpath, targetfullpath)            printandwritelog(u"檔案 %s 拷貝到 %s 成功" % (filefullpath, targetfullpath))#先處理替換前的前置操作,環境準備好之後執行替換操作    def ReplaceAllFiles(filepath, bydir):    sourceFileDir = filepath    if ":" in filepath:        printandwritelog(u"提供的本地路徑,走本地路徑檔案替換流程")    else:        printandwritelog(u"提供的FTP路徑,先下載檔案到本地後再執行替換流程")        sourceFileDir = cur_file_dir() + r"\testdir"        if os.path.isdir(sourceFileDir):            shutil.rmtree(sourceFileDir)        obj = netutilex.SFTP("192.168.1.100", "test", "testpwd")        obj.syncSftpDir(filepath, sourceFileDir)        obj.close()    ReplaceLocalFiles(sourceFileDir, bydir)

具體的最佳化操作有:

把函數checkinst和getallfiles的調用實現放到了其傳回值使用者ReplaceLocalFiles的函數體內,減少了2個參數的多次傳遞;
把函數ReplaceLocalFiles中具體的copy2操作進行了提取,因為bydir和非bydir最終都會走到這個操作;
把函數ReplaceFiles中對函數ReplaceLocalFiles的操作進行了提取,同時把函數ReplaceAllFiles和ReplaceFiles進行了合并。

最佳化後的結果看起來有沒有清爽很多?

Python 代碼最佳化實踐

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.