帶UI界面的代碼統計小工具--進程、隊列的並發應用

2021-03-02 光榮之路

文 | 遠走高飛 微信公眾號 周末求發展

一、實現思路:1.    遍歷目錄下的所有文件,將所有python,java,C文件路徑放到隊列裡。2.    創建多個進程,從隊列中獲取文件路徑,分別統計各類型文件的代碼行數。3.    將統計的結果,存放到一個變量裡,並且實現多進程間變量共享。4.    製作一個圖形界面,用於選擇文件夾和統計代碼,並展示統計結果。二、實現過程:1.實現函數,遍歷目錄下的所有文件,並將python,java,C源碼文件的絕對路徑放到一個隊列裡1)使用os.walk()遍歷文件夾下所有文件。
2)os.path.splitext()判斷文件後綴,過濾出後綴為[".py",".java",".c"]的文件。
3)使用os.path.join()拼成一個絕對路徑,放到隊列裡。
def get_files_path(dir_path,queue):    for root, dirs, files in os.walk(dir_path):        for file in files:            if os.path.splitext(file)[1] in [".py",".java",".c"]:                 file_path = os.path.join(root,file)                 queue.put(file_path)    

2.實現函數,統計代碼行
1)跳過多行注釋,不進行統計
2)跳過單行注釋,不進行統計
3)跳過空白行,不進行統計
4)其它的情況,統計代碼行數
def python_lines_count(file_path,encoding):    lines_count_python = 0    flag_python = 0      try:        with open(file_path, "r", encoding=encoding) as fp:            for line in fp:                if line.strip() == "'''" or line.strip()[1:4] == "'''" or line.strip()[                                                                          -3:] == "'''":                      flag_python += 1                  elif flag_python % 2 != 0:                      continue                elif line.strip() in string.whitespace:                      pass                elif line.lstrip()[0] == "#" or line.lstrip()[1] == "#":                      pass                else:                    lines_count_python += 1          return lines_count_python    except Exception as e:        print(e)        return 0
def java_c_lines_count(file_path,encoding): lines_count_java_c = 0 flag_java = 0 try: with open(file_path, "r", encoding=encoding) as fp: for line in fp: if line.strip()[:2] == "/*" or line.strip()[-2:] == "*/": flag_java += 1 elif flag_java % 2 != 0: continue elif line.strip() in string.whitespace: pass elif line.lstrip()[:2] == "//": pass else: lines_count_java_c += 1 return lines_count_java_c except Exception as e: print(e) return 0

3.實現函數,從隊列中獲取文件路徑,並統計代碼行1)使用queue.empty()判斷,當隊列不為空時,從隊列中獲取文件路徑
2)使用os.path.splitext(),根據文件後綴判斷,調用對應統計代碼行函數,計算每個文件的代碼行數
3)將每個文件的代碼行數,分別加到對應的進程共享變量total_count_python,total_count_java,total_count_c的value值中。
def get_code_lines(queue,total_count_python,total_count_java,total_count_c):      while not queue.empty():        file_path = queue.get()        file_path_suffix = os.path.splitext(file_path)[1]         if file_path_suffix == ".py":             try:                lines_count_python = python_lines_count(file_path,"utf-8")              except:                lines_count_python = python_lines_count(file_path, "gbk")               total_count_python.value += lines_count_python        elif file_path_suffix in [".java",".c"]:             lines_count_java_c = java_c_lines_count(file_path,"utf-8")                  if file_path_suffix == ".java":                total_count_java.value += lines_count_java_c            elif file_path_suffix == ".c":                total_count_c.value += lines_count_java_c    return

4.使用多進程與隊列,實現代碼行數統計

1)使用multiprocessing.Queue() ,定義一個隊列,用於存取代碼文件的絕對路徑。
2)使用multiprocessing.Value(「d」,0),定義主進程與子進程之間的共享變量,用於存儲每種類型的代碼行數。
3)使用multiprocessing.Process(),創建一個子進程,用於將文件路徑放到隊列中
4)使用multiprocessing.Process(),創建多個子進程,用於從隊列中獲取文件路徑,並統計代碼行數。

def get_total_code_lines(dir_path):#使用多進程與隊列,實現代碼行數統計    start = time.time()    queue = multiprocessing.Queue(1000)     #定義一個隊列,用於存取代碼文件的絕對路徑    total_count_python = multiprocessing.Value("d", 0)  # python代碼總行數,d表示數值,主進程與子進程共享這個value。(主進程與子進程都是用的同一個value)    total_count_java = multiprocessing.Value("d", 0)    # java代碼總行數    total_count_c = multiprocessing.Value("d", 0)       # c語言代碼總行數    p_get_path = multiprocessing.Process(target=get_files_path,args=(dir_path,queue)) #創建一個進程,用於獲取所有的代碼文件絕對路徑    p_get_path.start() #啟動進程    num_cpu = multiprocessing.cpu_count()  # 獲取當前計算機的cpu核數    p_get_lindes = [ multiprocessing.Process(target=get_code_lines,args=(queue,total_count_python,total_count_java,total_count_c)) for i in range(num_cpu)] #創建多個進程,計算每個文件的代碼行數    for p in p_get_lindes:#循環啟動進程        p.start()        p.join()    p_get_path.join() #執行join方法,待子進程全部結束後,再執行主進程的之後的代碼邏輯
print("python代碼總行數:",int(total_count_python.value)) print("java代碼總行數:", int(total_count_java.value)) print("c語言代碼總行數:", int(total_count_c.value)) end = time.time() tatal_time = end - start #計算統計代碼的總耗時 print("總耗時:",tatal_time) return int(total_count_python.value),int(total_count_java.value),int(total_count_c.value),tatal_time

5.使用tkinter做一個簡單的圖形界面

1)使用askdirectory()獲取選擇的文件夾路徑。
2)定義點擊事件,將獲取到的文件夾路徑做為參數傳入,調用統計代碼行的函數,計算代碼行數。
3)將計算的結果,更新到圖形界面。

def selectPath():    path_ = askdirectory()      path.set(path_)         
def click_submit(): dir_path=path.get() total_line_count = get_total_code_lines(dir_path) total_count_python.set(str(total_line_count[0])) total_count_java.set(str(total_line_count[1])) total_count_c.set(str(total_line_count[2])) total_time.set("%.3f" %total_line_count[3])
def add_Label_Entry(row,text,textvariable): Label(windows, text=text).grid(row=row, column=2,ipadx=5, pady=5) Entry(windows, textvariable=textvariable).grid(row=row, column=3,ipadx=5, pady=5)
if __name__ == '__main__': windows = Tk() windows.title("統計代碼行工具") windows.geometry("400x400") path = StringVar() total_count_python = StringVar() total_count_java = StringVar() total_count_c = StringVar() total_time = StringVar()
Label(windows,text = "代碼行統計路徑:").grid(row = 10, column = 2,ipadx=5, pady=50) Entry(windows, textvariable=path).grid(row=10, column=3,ipadx=20, pady=20) Button(windows, text="選擇", command=selectPath).grid(row=10, column=4,ipadx=20, pady=20)
Button(windows, text="開始統計", command=click_submit).grid(row=20, column=3,ipadx=60, pady=30) add_Label_Entry(60,"python代碼總行數:",total_count_python) add_Label_Entry(70, "java代碼總行數:",total_count_java) add_Label_Entry(80, "C語言代碼總行數:",total_count_c) add_Label_Entry(90, "總耗時(s):",total_time)
windows.mainloop()

6.最終效果1)點擊「選擇」按鈕,選擇需要統計代碼的目錄
2)點擊「開始統計」按鈕,進行統計
3)統計完成後,在下方展示統計結果



👆單擊連結直達、長按諮詢吳老師或公眾號內回復「2」

無論上課或自學,

你首先需要準備:

每天 2 小時+的學習時間,

每天堅持寫代碼的習慣!

有投入才有產出,

10k+的漲幅需要 1 年以上的努力!

祝你成功!

光榮之路出品

測試大佬和小白的故事

招聘QQ群:203715128

相關焦點

  • 21個免費的UI界面設計工具、資源及網站
    內容很豐富,適合用戶體驗設計師、界面設計師、產品設計師、JS前段開發、手機產品設計以及iPad和平板電腦產品設計等使用。 Lumzy 官方地址:http://www.lumzy.com/ Lumzy是一個網站應用和原型界面製作工具。使用Lumzy,您可以輕鬆創建UI模型並即時發送到客戶電腦中。
  • Python+PyQt架構:如何調用多個設計師窗口界面文件示例
    對於界面程序的設計,可以使用代碼構建,也可以藉助於其提供的設計師(Qt Designer)工具來構建,而從方便高效性上來講,第二種即使用設計師的方法應該是目前應用最多的一種界面設計方法。在使用設計師設計複雜的界面程序時,除設計主界面窗口文件外,一般還需設計其它的輔助子窗口文件,那麼在PyQt中,如何在主窗口中調用其它的子窗口文件呢?
  • Qt創建基於Widget小部件的應用程式
    本教程介紹如何使用 Qt小部件創建一個應用程式:文本查找器。它是 Qt UI 工具文本查找器示例的簡化版本。應用程式用戶界面是通過使用 Qt 設計器從 Qt 小部件構建的。應用程式邏輯使用代碼C++代碼編輯器以代碼編寫。
  • 圖形界面編程技巧,用Python中PyQt5庫快速創建一個應用程式框架
    Qt是面向對象的框架,使用特殊的代碼生成擴展(稱為元對象編譯器(Meta Object Compiler, moc))以及一些宏,Qt很容易擴展,並且允許真正地組件編程。2008年,Qt Company科技被諾基亞公司收購,Qt也因此成為諾基亞旗下的程式語言工具。2012年,Qt被Digia收購。
  • 大話程序猿眼裡的高並發
    高並發會來帶的後果下面我進行實例分析,簡單粗暴,動態分析,純屬本人個人經驗分享,如有說錯,或者有更好的建議或者意見的請留言,大家一起成長。並發下的數據處理:通過表設計,如:記錄表添加唯一約束,數據處理邏輯使用事物防止並發下的數據錯亂問題通過服務端鎖進程防止包並發下的數據錯亂問題這裡主要講述的是在並發請求下的數據邏輯處理的接口,如何保證數據的一致性和完整性,這裡的並發可能是大量用戶發起的
  • 深入學習SAP UI5框架代碼系列之一:UI5 Module的懶加載機制
    ,沒有任何後臺API的依賴 介紹的腳手架應用,創建一個只包含一個Button控制項的UI5應用:網上有一種說法,頁面加載的資源,是通過網絡加載的資源,以及從瀏覽器緩存讀取的資源總和,因此會出現Chrome開發者工具裡顯示的頁面加載的資源尺寸大於網絡傳輸數據量的情況。這種說法不完全正確。更準確的說,頁面加載資源統計的是前端頁面加載的所有資源,經過解壓之後的原始大小。
  • 並發的本質:線程和進程?
    本篇收錄於《offer快到碗裡來》寫在之前 "進程和線程有何區別?" 這個問題是校招面試中最最常見的問題了。很多人討厭這種背誦課本概念的問題,還請看管打住,稍後再噴;該問題還真是一個值得思考的問題。我們常常掛在嘴邊的,你有沒有經歷過什麼高並發項目,有沒有比較難以解決的高並發問題。面試時,如果說沒有遇到高並發問題似乎低人一等。
  • RabbitMQ 消費端限流、TTL、死信隊列
    :RabbitMQ 簡介以及使用場景,以及帶大家進行了:手把手帶你Springboot整合RabbitMq ,一篇講完,然後還帶大家用Hyperf+RabbitMQ+WebSocket實現大屏幕消息推送(藍字點擊可跳轉),今天這篇,為大家講講RabbitMQ的消費端限流、TTL、死信隊列相關內容。
  • Event Loop - 事件隊列
    ,會將所有的圍觀函數加到微觀隊列等待,當前宏任務處理完畢後,開始逐個處理微任務,當微任務執行處理完成,會檢查是否需要更新ui,如果是則重新渲染ui。代碼是在一秒鐘後才加入事件隊列,之後等待執行。') },0); return new Promise(function (resolve) { console.log('3'); resolve(); }) }};obj.func().then(function () { console.log('4')});console.log('5');主線進程及其微觀進程執行完畢
  • 前端開發者的福音:根據UI設計圖自動生成GUI骨架代碼
    某些工具聲稱可以在給定 UI 設計圖的情況下自動生成 GUI 骨架代碼,但這些工具由於是基於人工設計的視覺理解規則實現的,因此功能十分有限,不能處理真實複雜的 UI 設計(如圖 1)。自動化 UI 探索工具使用 Android 模擬器來運行 Android 應用程式,存儲成對的 UI 截圖和相應的運行時 GUI 組件層次結構。
  • 【UI分享】界面設計工具都在這裡了
    除此之外,Sketch另一個特點就是擁有很多改善使用體驗的小設計。Sketch最實用和受歡迎的功能之一是伴侶應用Sketch Mirror,用戶的行動裝置和電腦端Sketch能夠協同工作。設計師可以連接iPhone到Mac上,並在行動裝置上實時測試自己本地端的設計。現在聽起來這沒什麼,但在2010年,這絕對是產品的殺手鐧之一。
  • Elixir 與 Go 多角度對比:背景+編程風格+並發處理
    在使用並發和分布式邏輯時,Erlang定義了一套捆綁在「OTP」下最佳實踐模式。多數情況下,在 Elixir 的代碼中,你永遠都接觸不到原生的spawn 和 send/receive 函數,這樣就推遲了功能的抽象。Task 的封裝實現了簡單的async/await風格的調用。Agent為並發的進程維護和更新共享狀態。GenServer 可用來實現更複雜的自定義邏輯。
  • 作業系統原理之進程管理
    進程隊列二、進程的控制進程的創建:用戶登錄 作業調度 提供服務 應用請求。1、多道程序環境下進程之間的關係:資源共享關係:保證各進程以互斥的方式訪問臨界資源相互合作關係:保證相互合作的各進程協調執2、以互斥方式訪問的共享資源稱為臨界資源,進程中訪問臨界資源的那段代碼稱為臨界區
  • 並發編程 71 道題及答案全送上!
    進程是作業系統分配資源的最小單元,線程是作業系統調度的最小單元。一個程序至少有一個進程,一個進程至少有一個線程。3、什麼是多線程中的上下文切換?多線程會共同使用一組計算機上的CPU,而線程數大於給程序分配的CPU數量時,為了讓各個線程都有執行的機會,就需要輪轉使用CPU。
  • 並發工具類閉鎖CountDownLatch介紹與源碼解析
    前面看了ReentrantLock的源碼,而閉鎖CountDownLatch可能大家見得少,但是他也是AQS下的一個並發工具類,今天來簡單介紹一下它。接下來我們來看稍微複雜的一個經典例子,代碼如下圖:這個方法可以實現指定並發數的情況下任務執行用時,因為創建線程有時間差,所以所有線程創建好先阻塞,等待一起喚醒。然後利用endLatch來控制統計線程的阻塞與喚醒,實現了很精確的計算並發下任務執行用時。
  • Android 面試:用廣播 BroadcastReceiver 更新 UI 界面真的好嗎?
    下面請允許我用「柳學兄」的思路帶大家進入面試營。BroadcastReceiver 內部基本原理是什麼?Android 的廣播 BroadcastReceiver 是一個全局的監聽器,主要用於監聽 / 接收應用發出的廣播消息,並作出響應。
  • 大話程序猿眼裡的高並發 - OSCHINA - 中文開源技術交流社區
    高並發會來帶的後果下面我進行實例分析,簡單粗暴,動態分析,純屬本人個人經驗分享,如有說錯,或者有更好的建議或者意見的請留言,大家一起成長。並發下的數據處理:通過表設計,如:記錄表添加唯一約束,數據處理邏輯使用事物防止並發下的數據錯亂問題通過服務端鎖進程防止包並發下的數據錯亂問題這裡主要講述的是在並發請求下的數據邏輯處理的接口,如何保證數據的一致性和完整性,這裡的並發可能是大量用戶發起的,也可能攻擊者通過並發工具發起的並發請求如例子:通過表設計防止並發導致數據錯亂需求點
  • 使用Python製作一個帶GUI界面的詞雲自動生成工具(一)
    嗯,比如老闆想讓你統計一下……);想知道一個名人一篇講話稿中的主要觀點和立場(對時局和觀點進行分析時使用),等等諸多想知道……在做引言中的這些統計時如果我們有一個稱手的工具,把文章或者講話稿放到工具裡面,簡單進行一下設置,然後輸出關於這篇文章或講話稿的詞雲(不敢想像,這樣節省了多少人力),這個工具像魔法箱一樣,是不是很酷?
  • Web經典B/S快速開發框架,強大後臺+簡潔UI一體化開發工具
    框架優勢:1.快速開發框架中有多套開發模板,選擇模板後按照嚮導操作可自動產生包含界面在內的所有代碼。如果需要二次開發,可以直接修改生成的原始碼。2.界面風格簡潔(多套UI)、大氣、操作便捷,符合國人的審美觀念。3.採用 SOA 架構,系統核心功能均可以通過服務的方式提供給外部調用,方便系統與 ERP 系統及周邊系統、硬體設備接口交互能力,解決企業信息化孤島問題。