基于wxPython的python代码统计工具
近来学习python和wxpython,就顺手做了一个小工具:基于wxPython的python代码统计工具,主要功能是可以通过wxpython的gui界面选择一个目录,然后工具将递归搜索该目录找出所有以.py结尾的文件,并对这些文件进行统计,输出包括总的代码行数,注释行数,空行数等。
开发工具:python2.7 + wxPython2.8.11 + wxFormBuilder。
程序界面如下:
代码如下:
pycodecounter.py:
1 import string
2 import sys
3
4 class PyCodeCnt():
5 def __init__(self):
6 self.inFileList = []
7 self.blankLines = 0
8 self.commentLines = 0
9 self.codeLines = 0
10 self.totalLines = 0
11
12 def handlefile(self, fileName):
13 try:
14 f = open(fileName, "r")
15 for line in f.readlines():
16 for char in line:
17 if char == "\n":
18 self.blankLines += 1
19 break
20 if char == "#":
21 self.commentLines += 1
22 break
23 elif (char not in string.whitespace) and (char != "#"):
24 self.codeLines += 1
25 break
26 f.close()
27 self.totalLines += self.blankLines
28 self.totalLines += self.commentLines
29 self.totalLines += self.codeLines
30 return (self.codeLines, self.commentLines, self.blankLines, self.totalLines)
31
32 except IOError:
33 print( "Error opening \"" + fileName + "\", skipping...\n")
34
maindlg_gui.py:
1 # -*- coding: utf-8 -*-
2
3 ###########################################################################
4 ## Python code generated with wxFormBuilder (version Sep 8 2010)
5 ## http://www.wxformbuilder.org/
6 ##
7 ## PLEASE DO "NOT" EDIT THIS FILE!
8 ###########################################################################
9
10 import wx
11
12 ###########################################################################
13 ## Class MainDialogGUI
14 ###########################################################################
15
16 class MainDialogGUI ( wx.Dialog ):
17
18 def __init__( self, parent ):
19 wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"PyCodeCounter", pos = wx.DefaultPosition, size = wx.Size( 671,384 ), style = wx.DEFAULT_DIALOG_STYLE|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX|wx.RESIZE_BORDER )
20
21 self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
22 self.SetForegroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNTEXT ) )
23 self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT ) )
24
25 bSizerDlg = wx.BoxSizer( wx.VERTICAL )
26
27 bSizerFileList = wx.BoxSizer( wx.VERTICAL )
28
29 self.m_tcFileList = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.HSCROLL|wx.TE_MULTILINE|wx.TE_READONLY )
30 bSizerFileList.Add( self.m_tcFileList, 1, wx.ALL|wx.EXPAND, 5 )
31
32 bSizerDlg.Add( bSizerFileList, 1, wx.EXPAND, 5 )
33
34 bSizerRes = wx.BoxSizer( wx.VERTICAL )
35
36 self.m_tcRes = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.HSCROLL|wx.TE_MULTILINE|wx.TE_READONLY )
37 bSizerRes.Add( self.m_tcRes, 1, wx.ALL|wx.EXPAND, 5 )
38
39 bSizerDlg.Add( bSizerRes, 1, wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 5 )
40
41 bSizerBtn = wx.BoxSizer( wx.HORIZONTAL )
42
43 self.m_dirPicker = wx.DirPickerCtrl( self, wx.ID_ANY, wx.EmptyString, u"Select a folder", wx.DefaultPosition, wx.DefaultSize, wx.DIRP_DEFAULT_STYLE )
44 bSizerBtn.Add( self.m_dirPicker, 1, wx.ALL|wx.EXPAND, 5 )
45
46 self.m_btnOK = wx.Button( self, wx.ID_ANY, u"Count", wx.DefaultPosition, wx.DefaultSize, 0 )
47 bSizerBtn.Add( self.m_btnOK, 0, wx.ALL, 5 )
48
49 self.m_btnExit = wx.Button( self, wx.ID_ANY, u"Exit", wx.DefaultPosition, wx.DefaultSize, 0 )
50 bSizerBtn.Add( self.m_btnExit, 0, wx.ALIGN_CENTER|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
51
52 bSizerDlg.Add( bSizerBtn, 0, wx.ALIGN_BOTTOM|wx.ALIGN_CENTER|wx.EXPAND, 5 )
53
54 self.SetSizer( bSizerDlg )
55 self.Layout()
56
57 self.Centre( wx.BOTH )
58
59 # Connect Events
60 self.m_dirPicker.Bind( wx.EVT_DIRPICKER_CHANGED, self.OnDirChanged )
61 self.m_btnOK.Bind( wx.EVT_BUTTON, self.OnOK )
62 self.m_btnExit.Bind( wx.EVT_BUTTON, self.OnClose )
63
64 def __del__( self ):
65 pass
66
67
68 # Virtual event handlers, overide them in your derived class
69 def OnDirChanged( self, event ):
70 event.Skip()
71
72 def OnOK( self, event ):
73 event.Skip()
74
75 def OnClose( self, event ):
76 event.Skip()
77
78
79
maindlg.py:
1 '''
2 Created on 2010-10-17
3
4 @author: qilei
5 '''
6 import maindlg_gui
7 import pycodecounter
8 import os
9
10 class MainDialog( maindlg_gui.MainDialogGUI ):
11 def __init__( self, parent ):
12 maindlg_gui.MainDialogGUI.__init__( self, parent )
13 self.wildcard = "Python source files(*.py)|*.py|All files(*.*)|*.*"
14 self.dir = ''
15 self.fileList = []
16 self.totalLines = 0
17 self.codeLines = 0
18 self.CommentLines = 0
19 self.BlackLines = 0
20
21 def OnDirChanged( self, event ):
22 self.dir = self.m_dirPicker.GetPath()
23 event.Skip()
24
25 def OnOK( self, event):
26 ''' Try to read and handle every py-files in the list and
27 update results to dialog.
28 '''
29 self.totalLines = 0
30 self.codeLines = 0
31 self.CommentLines = 0
32 self.BlackLines = 0
33 fileList = self.walkdir(self.dir)
34 self.fileList = [] # reset to empty
35 for fileName in fileList:
36 if fileName.endswith('.py'):
37 self.fileList.append(fileName)
38 for eachFile in self.fileList:
39 codeCntRes =self.readfile(eachFile)
40 if codeCntRes:
41 self.totalLines += codeCntRes[3]
42 self.codeLines += codeCntRes[0]
43 self.CommentLines += codeCntRes[1]
44 self.BlackLines += codeCntRes[2]
45 strRes = ('Total Lines', 'Code Lines', 'Comment Lines', 'Blank Lines');
46 strRes = str(strRes)
47 strRes += str((self.totalLines, self.codeLines, self.CommentLines, self.BlackLines))
48 self.m_tcFileList.Clear()
49 #append files to text control
50 self.m_tcFileList.AppendText('Total valid files: ' + str(len(self.fileList)) + '\r')
51 for eachFile in self.fileList:
52 self.m_tcFileList.AppendText(eachFile + '\r')
53 #update result showing
54 self.m_tcRes.Clear()
55 self.m_tcRes.AppendText('Total Lines: ' + str(self.totalLines) + '\r')
56 self.m_tcRes.AppendText('Code Lines: ' + str(self.codeLines) + '\r')
57 self.m_tcRes.AppendText('Comment Lines: ' + str(self.CommentLines) + '\r')
58 self.m_tcRes.AppendText('Blank Lines: ' + str(self.BlackLines) + '\r')
59 event.Skip()
60
61 def OnClose( self, event ):
62 self.Destroy()
63 event.Skip()
64
65 def walkdir(self, dir):
66 ''' walk dir and its sub-dir to get py-files list'''
67 resFiles = []
68 tuples = os.walk(dir)
69 for i in tuples:
70 dirpath = i[0]
71 filenames = i[2]
72 for file in filenames:
73 resFiles.append( os.path.join(dirpath, file) )
74 return resFiles
75
76 def readfile( self, fileName ):
77 ''' Read file 'fileName' and get it's code info.'''
78 if fileName:
79 plc = pycodecounter.PyCodeCnt()
80 return plc.handlefile(fileName)
81 else:
82 return None
83
84
85
main.py:
1 import wx
2 import maindlg
3
4 def main():
5 app = wx.PySimpleApp()
6 dlg = maindlg.MainDialog(None)
7 dlg.Show()
8 app.MainLoop()
9
10 if __name__ == '__main__':
11 main()
12