之前在做一些数据统计方面的工作,主要是用脚本去跑一些帐单,开始做的时候用shell,后来发现还是python可读性高,总结一下
之前写过的python统计的框架,给喜欢PYTHON的朋友分享一下
 
假设日志目录如下,先按月分目录,每级下按业务分目录,每级业务下按天分不天的日志。
 
框架主要实现以下功能:
1.配置文件管理
2.一个日期范围,跑范围内的帐单
3.很方便的处理文件路径问题
4.通过python的datetime库来实现日期转化,运算等。
5.封装MYSQL操作,封装了ON DUPLICATE KEY UPDATE 的功能,调用很方便。
 
源码如下,主要是三个文件
Util.py
View Code
 1 #coding=utf-8
2 '''
3 Created on 2011-10-19
4
5 @author: lincolnlin
6 '''
7 import string
8 import datetime
9 import re
10
11 oneday=datetime.timedelta(days=1)
12 today=datetime.date.today()-oneday*3
13
14 def toInt(i,default):
15 '''整数检查'''
16 try:
17 ret=int(i)
18 except Exception,err:
19 ret=default
20 finally:
21 return ret
22
23 def toPosInt(i,default):
24 '''非负整数检查'''
25 try:
26 ret=int(i)
27 if ret<0:
28 ret=default
29 except Exception,err:
30 ret=default
31 finally:
32 return ret
33
34 def strtodate(s):
35 '''处理类似于2011-11-11 的字符串,转化成日期datetime.date'''
36 l=s.split('-')
37 return datetime.date(int(l[0]),int(l[1]),int(l[2]))
38
39 def strToTime(start):
40 '''处理类似于20111202101930 的字符串,转化成时间 datetime.datetime'''
41 return datetime.datetime(int(start[0:4]),int(start[4:6]),int(start[6:8]),int(start[8:10]),int(start[10:12]),int(start[12:14]))
42
43 def strToTime2(source):
44 '''处理类似于2011-12-01 00:00:03 的字符串,转化成时间 datetime.datetime'''
45 p=re.compile(r'''
46 (?P<year>\d{4}) #string1
47 \-
48 (?P<month>\d{2}) #month
49 \-
50 (?P<day>\d{2})
51 \s
52 (?P<hour>\d{2})
53 :
54 (?P<minute>\d{2})
55 :
56 (?P<second>\d{2})
57 '''
58 ,re.X)
59 m=p.match(source)
60 if m:
61 return datetime.datetime(int(m.group('year')),int(m.group('month')),int(m.group('day')),int(m.group('hour')),int(m.group('minute')),int(m.group('second')))
62 else:
63 return None
64
DBModule.py
View Code
#coding=utf-8 
'''
Created on 2011-10-19

@author: lincolnlin
'''
import MySQLdb
import datetime
from string import Template
from ConfigParser import ConfigParser

class mysqlDB(object):
'''
MySQLdb的封装库
'''
def __init__(self,database):
'''
初始化函数
@param database:要连接的数据库
@status: self.conn self.cursor,self.today建立
'''
try:
#读配置 文件
#读取配置 文件
CONFIGFILE=r'C:\Users\lincolnlin\Documents\Aptana Studio 3 Workspace\logFrame\src\pyFrame\config.ini'
config=ConfigParser()
config.read(CONFIGFILE)
host=config.get('db', 'host')
user=config.get('db','user')
passwd=config.get('db','passwd')
conn=MySQLdb.connect(host,user,passwd,database)
print 'connect to db...' if conn else 'disconnect db....'
conn.autocommit(True)
self.conn=conn
self.cursor=conn.cursor()

except Exception, err:
print err
if(self.conn):
conn.close()


def actQuery(self,sql,param):
'''
执行返回影响行数
'''
cursor=self.cursor
num_affected_rows = cursor.execute(sql,param)
self.num_affected_rows=num_affected_rows
return num_affected_rows

def getRow(self,sql,param):
'''
执行返回第一行
'''
cursor=self.cursor
num_affected_rows =cursor.execute(sql,param)
self.num_affected_rows=num_affected_rows
result=cursor.fetchone()
return result

def getRows(self,sql,param):
'''
执行返回全部行
'''
cursor=self.cursor
num_affected_rows = cursor.execute(sql,param)
self.num_affected_rows=num_affected_rows
result=cursor.fetchall()
return result
def replace(self,table,StatDate,dict):
'''
根据主键StatDate更新或插入dict
@attention: dict中的value只能是数字格式
'''
print 'replace'
sql1='INSERT INTO '+table+' (StatDate,'
sql2="VALUES("+self.escape(StatDate)+',';
sql3='ON DUPLICATE KEY UPDATE '
keys=dict.keys()
for k in range(len(dict)):
if k==len(dict)-1:
sql1+=keys[k]+')'
sql2+=str(dict[keys[k]])+')'
sql3+=str(keys[k])+'='+str(dict[keys[k]])
else :
sql1+=keys[k]+','
sql2+=str(dict[keys[k]])+','
sql3+=str(keys[k])+'='+str(dict[keys[k]])+','
sql=sql1+sql2+sql3
print sql
return self.actQuery(sql, ())

def escape(self,s):
'''return the 'string' of string'''
ret=Template("'$str'")
return ret.safe_substitute(str=s)

def __del__(self):
if self.conn:
self.conn.close()
if self.cursor:
self.cursor.close()
print 'del ....'

logFrame.py
View Code
 1 #coding=utf8
2 '''
3 Created on 2011-10-21
4 @author: lincolnlin
5 '''
6 import sys
7 import datetime
8 from Util import *
9 import os
10 from ConfigParser import ConfigParser
11
12 class logBase(object):
13 '''
14 日志统计的框架
15 '''
16 def __init__(self,argv,bills):
17 '''
18 Constructor,@param argv:sys.argv @param bills:(.多个不同的账单目录.)
19 '''
20 #读取配置 文件
21 CONFIGFILE=r'C:\Users\lincolnlin\Documents\Aptana Studio 3 Workspace\logFrame\src\pyFrame\config.ini'
22 config=ConfigParser()
23 config.read(CONFIGFILE)
24 self.stardir=config.get('path', 'startdir')
25
26 print '<datefrom><dateto>'
27
28 #设置程序运行环境变量
29 self.datefrom=today
30 self.dateto=today
31 self.bills=bills #帐单类型
32
33 #设定起始时间段
34 if len(argv)==3:
35 self.datefrom=strtodate(argv[1])
36 self.dateto=strtodate(argv[2])
37 elif len(argv)==2:
38 print argv
39 self.datefrom=strtodate(argv[1])
40 elif len(argv)==1:
41 pass
42 else:
43 print 'error usage'
44
45 def loop(self):
46 ''' 统计的循环体'''
47 tmpdate=self.datefrom;
48 while tmpdate<=self.dateto:
49 self.now=tmpdate
50 self.main(tmpdate)
51 tmpdate+=oneday
52 def main(self,date):
53 ''' 主要统计过程 ,子类需重写该方法 '''
54 def getfile(date):
55 smonth=str(date.year)+datetime.date.strftime(date,'%m')
56 sdate=smonth+datetime.date.strftime(date,'%d')
57 #print smonth,sdate
58 curfiles=[]
59 for bill in self.bills:
60 path=os.path.join(self.stardir,smonth,bill,sdate+'.txt')
61 print path
62 curfile=path if os.path.exists(path) else None
63 curfiles.append(curfile)
64 return curfiles
65 self.curfiles=getfile(date)
66 print 'do the main thing to ',self.curfiles
config.ini
View Code
1 [path]
2 startdir=C:\Users\lincolnlin\Desktop\TexasHoldem\log
3
4 [db]
5 host=127.0.0.1
6 user=root
7 passwd=
 
调用的方式:
testFrame.py
View Code
#!/usr/bin/env python
#
coding=utf-8
'''
Created on 2011-11-28
@author: lincolnlin
'''

import sys
from pyFrame.logFrame import logBase
from pyFrame.Util import *
from pyFrame.DBModule import *

class TestFrame(logBase):
def __init__(self,params,bill):
logBase.__init__(self, params,bill)
self.db=mysqlDB('GameStat') #传入所在的数据库

def preprocess(self,file):
for line in file:
record= line.split('|')
yield record[0],record[1]

def main(self,date):
''' 通过self.curfiles可获得相对应的所有当前帐单 '''
logBase.main(self, date)
for file in self.curfiles:
if not file:
return #有一个文件为空则停止处理
f=open(self.curfiles[0],'r')
for uin,money in self.preprocess(f):
'''.....主要逻辑'''
f.close()
self.db.replace('ActMoneyDaily',date,{'key1':1,'key2':2})
testFrame=TestFrame(sys.argv,('money',)) #这里传一个列表,表示多少种帐单类型,
testFrame.loop()
总体上也比较简单,温故而知已,python在解决此类编程问题上,绝对是不二解决,一门把电池在包括的内的编程语言。
posted on 2012-02-20 19:41  lincolnlin  阅读(1794)  评论(0编辑  收藏  举报