阿里山QQ

导航

python递归、collections系列以及文件操作进阶

global
        log 127.0.0.1 local2
        daemon
        maxconn 256
        log 127.0.0.1 local2 info
defaults
        log global
        mode http
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms
        option  dontlognull

listen stats :8888
        stats enable
        stats uri       /admin
        stats auth      admin:1234

frontend oldboy.org
        bind 0.0.0.0:80
        option httplog
        option httpclose
        option  forwardfor
        log global
        acl www hdr_reg(host) -i www.oldboy.org
        use_backend www.oldboy.org if www

backend www.oldboy.org
       server  100.1.7.9 100.1.7.9 weight 20 maxconn 30



########################################
配置文件增删查

1、查
    输入:www.oldboy.org
    获取当前backend下的所有记录

2、新建
    输入:
        arg = {
            'bakend': 'www.oldboy.org',
            'record':{
                'server': '100.1.7.9',
                'weight': 20,
                'maxconn': 30
            }
        }

3、删除
    输入:
        arg = {
            'bakend': 'www.oldboy.org',
            'record':{
                'server': '100.1.7.9',
                'weight': 20,
                'maxconn': 30
            }
        }

需求
上文件操作方式练习作业--结合Flag标志位极好的例子--需求

 

递归:

(1)递归就是在过程或函数里调用自身;
(2)在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。

在python中如果函数没有return,就会return为None

def func(arg1,arg2):
    if arg1 == 0:
        print arg1,arg2
    arg3 = arg1 + arg2
    if arg3 > 1000:
        return arg3
    else:
        func(arg2,arg3)
result = func(0,1)
print result


结果为:
0 1
None

 

正确地递归函数为:

def func(arg1,arg2):
    if arg1 == 0:
        print arg1,arg2
    arg3 = arg1 + arg2
    if arg3 > 1000:
        return arg3
    return func(arg2,arg3)
result = func(0,1)
print result

 

 

 

计算器作业思路:

    循环:递归

    将括号中的内容计算出来之后依次递归

练习题1:将列表[11,22,33,44,55,66,77,88,99]大于66的值放入第一个key中,将小于66的值放入字典第二个key中;

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

num_list = [11,22,33,44,55,66,77,88,99]

dict_list = {'k1':[],
             'k2':[],
}

for item in num_list:
    if item <=60:
        dict_list['k1'].append(item)
    else:
        dict_list['k2'].append(item)

print dict_list

  

练习题2:上题中,如果字典中没有key值如何处理(只有空字典)

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

num_list = [11,22,33,44,55,66,77,88,99]

dict_list ={}

for item in num_list:
    if item <=60:
        if 'k1' in dict_list.keys():
            dict_list['k1'].append(item)
        else:
            dict_list['k1'] = [item,] #统一一下规范,都加逗号
    else:
        if 'k2' in dict_list.keys():
            dict_list['k2'].append(item)
        else:
            dict_list['k2']=[item,]
print dict_list

  

 

练习题3:将文本内容alex|123|1

                           eric|123|1

                           tony|123|1放入字典中,第一个名字为key

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

f = file(r'log','r')
line_list = f.readlines()
f.colse()
dic = {}
for line in line_list:
    line = line.strip().split('|')
    dic[line[0]]=line[1:]
print dic

 

一、Collections系列

1、collections系列之计数器

>>> import collections
>>> c1=collections.Counter('abcd')                       #计数器,对象为字符串或列表
>>> c1
Counter({'a': 1, 'c': 1, 'b': 1, 'd': 1})
>>> c1=collections.Counter([11,22,33,11])
>>> c1
Counter({11: 2, 33: 1, 22: 1})

 

>>> c1=collections.Counter('abcd')
>>> c1
Counter({'a': 1, 'c': 1, 'b': 1, 'd': 1})
>>> c2=collections.Counter('abc')
>>> c2
Counter({'a': 1, 'c': 1, 'b': 1})
>>> c1.update(c2)                #元素个数叠加
>>> c1
Counter({'a': 2, 'c': 2, 'b': 2, 'd': 1})

 

>>> c1.clear()   #清除内容
>>> c1
Counter()

 

>>> c1
Counter({'a': 1, 'c': 1, 'b': 1, 'd': 1})    #将前n个k,v值当做元组放入列表中
>>> c1.most_common(2)
[('a', 1), ('c', 1)]

 

>>> c1.elements()      #类似于xreadlines(),是一个迭代器,只有循环时才可以显示出来
<itertools.chain object at 0x92697cc>

 

2、collections之有序字典(与字典用法相同)

>>> o1=collections.OrderedDict()    #创建有序字典,区别是内部维护一个列表,列表是有序的
>>> o1
OrderedDict()
>>> o1['k1']=1
>>> o1
OrderedDict([('k1', 1)])

 

3、默认字典(defaultdict):为字典里的value设置默认类型

字典value的默认类型为None,即为

>>> dic = {'k1':None}   #None没有append方法
>>> dic
{'k1': None}

1 >>> import collections
2 >>> 
3 >>> dic = collections.defaultdict(list)     #定义字典,并将value值设为list
4 >>> dic['k1']
5 []
6 >>> dic['k1'].append(1)

4、collections之命名元组----->创建类

一般是:创建类--->使用类创建对象--->使用对象

对于现有的类:直接使用类创建对象--->使用对象

对于元组而言,访问元组对象中的元素,必须使用下标才行,那么如何才能不需要下标来取值呢?

#创建一个扩展的tuple类
>>> Mytuple = collections.namedtuple('Mytuple',['x','y'])
>>> new = Mytuple(1,2)  #实例化
>>> new
Mytuple(x=1, y=2)
>>> new.x   #通过该方法访问值
1
>>> new.y
2

5、collections之双向队列(deque)-----线程安全

>>> q = collections.deque() #创建队列
>>> q.append(1)   #将1添加到队列中
>>> q.append(2)
>>> q.append(4)
>>> q
deque([1, 2, 4])
>>> q.pop()  #删除(从右边开始)
4
>>> q.popleft()   #从左边删除
1

除了deque,其他python标准模块也提供队列机制,queue,mutiprocessing,asyncio,heapq;

 

6、单向队列(Queue)-----线程安全

>>> import Queue
>>> q=Queue.Queue(10)    #创建队列,放10个元素
>>> 
>>> q.put(1)    #往队列中添加数据
>>> q.put(2)
>>> q.put(3)
>>> q.put(4)
>>> q
<Queue.Queue instance at 0xa3cbc8c>

>>> q.get()    #从队列中往出拿数据,相当于pop
1

队列与与栈如何区别:
    队列:FIFO
    栈:弹夹

7、迭代器和生成器原理

   >>> xrange(10):创建时不会在内存中创建对象,只有在循环时才会创建

  在数据库创建连接池时,为节省资源,用生成器创建。

8、下标式循环以及冒泡算法

如何将a、b的值互换:

>>> a = 123
>>> b = 321
>>> 
>>> temp = a
>>> a = b
>>> b = temp
>>> a
321
>>> b
123

下标式循环:

>>> for m in range(len(li)-1):
...     print li[m],
... 
22 6 99 11

 冒泡算法:

>>> li = [13,22,6,99,11]
>>> for m in range(len(li)-1):
...     for n in range(m,len(li)-1):
...         if li[m] > li[n]:
...             temp = li[m]
...             li[m] = li[n]
...             li[n] =temp
... 
>>> li
[6, 13, 22, 99, 11]

9、内置函数

函数的分类:内置函数、自定义函数、导入函数

>>> print vars()   #内置函数,拿到当前模块中的所有变量
{'temp': 22, '__builtins__': <module '__builtin__' (built-in)>, 'm': 3, 'li': [6, 13, 22, 99, 11], 'n': 3, 'tab': <module 'tab' from '/usr/lib/python2.7/dist-packages/tab.pyc'>, '__name__': '__main__', '__package__': None, '__doc__': None}

其中:

__file__:文件路径

__doc__:注释

__name__:被执行的文件被赋值为__main__

 

内存级别函数:

    reload:被reload的模块之前必须被import过,一般在被reload的模块内容改变之后使用;

    id

    is:内存地址相同

计算级别:

    cmp(2,3)

    abs()

    bool()

    divmod(10,3)分页

    max()

    min()

    sum()

    pow(2,11):2的11次方

all和any:all()接受一个序列,判断所有值为真,返回真,在输入用户名和密码的时候,一次性输入,可以判断输入的是否有空值;

 

enumerate

>>> for k,v in enumerate([11,22,33,44,55],1):    #遍历下标和列表,序号从1开始
...     print k,v
... 
1 11
2 22
3 33
4 44
5 55

10、函数式编程和面向对象编程

11、函数式编程之发邮件

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

def email(message):
    msg = MIMEText(message,'plain','utf-8')

    msg['From'] = formataddr(["Charles",'qq_c123@163.com'])    #源
    msg['To'] = formataddr(["走人",'1812352106@qq.com'])  #目标
    msg['Subject'] = "主题"

    server = smtplib.SMTP("smtp.163.com",25)
    server.login("qq_c123@163.com","sXXXXXX")
    server.sendmail("qq_c123@163.com",['1812352106@qq.com',],msg.as_string())
    server.quit()


if __name__ == '__main__':
    cpu = 100
    disk = 500
    raw = 50
    for i in range(1):
    if cpu > 90:
            alert='CPU有告警'
            email(alert)
        if disk > 90:
            alert = '磁盘有告警'
            email(alert)
        if raw > 90:
            alert = 'raw有告警'
            email(alert)
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

def email(message,receiver):
    msg = MIMEText(message,'plain','utf-8')

    msg['From'] = formataddr(["常强强",'qq_c123@163.com'])
    msg['To'] = formataddr(["走人",'1812352106@qq.com'])
    msg['Subject'] = "主题"

    server = smtplib.SMTP("smtp.163.com",25)
    server.login("qq_c123@163.com","start33333")
    server.sendmail("qq_c123@163.com",[receiver,],msg.as_string())    #发送邮件到多个
    server.quit()


li = ["qq_c123@163.com","alex111@126.com"]
for item in li:
    emali("cpu报警",item)

if __name__ == '__main__':
    cpu = 100
    disk = 500
    raw = 50
    for i in range(1):
    if cpu > 90:
            alert='CPU有告警'
            email(alert)
        if disk > 90:
            alert = '磁盘有告警'
            email(alert)
        if raw > 90:
            alert = 'raw有告警'
            email(alert)

 

函数的返回值:

     a、如果函数没有返回值,那么返回值就为None;

     b、函数返回值可以复制给某个变量

12、函数的参数

a、普通参数:定义了几个形参,就要传几个实参;

b、默认参数:默认参数放在形参的最后;

c、动态参数:def func(*args):接受多个参数

                   def func(**kwargs):有两种传值方式

                   第一种:

>>> func(k1=123)
{'k1': 123}

                   第二种:

>>> dic = {'k1':123}
>>> func(**dic) {'k1': 123}

函数 def func(*args,**kwargs):可以接受实参为列表和字典

 

13、文件操作

打开操作:

  r:打开文件,指针在最前面

     w:将原来的内容清空掉,然后重写,指针在最前面

     a:可读、可写(以追加的方式写),指针在最后

     +:只有r+(读写)有意义,指针放在开头,新写入的数据会依次替代原来的数据,没有替代的继续保留;

     r+U:在读的时候,将"\r\n"转为"\n",U只能和r一起使用;

>>> obj = open('log','r')
>>> obj.read()
'test123\r\n'
>>> obj.close()
>>> obj = open('log','r+U')
>>> obj.read()
'test123\n'

obj.tell():返回文件读写位置的指针;

obj.read():将文件内容读到一个字符串当中;

obj.truncate():从指针指向的位置开始截断数据,保留前面的,丢弃后面的,在r+(读写)的时候用这种方法丢掉原来的数据;

rb/wb/ab:如果是跨平台的话,使用二进制;

 

操作文件:

     f.next()    #一次读一行

>>> seq = ["This is frist line\n","This is second line"]
>>> obj.writelines(seq)    #写入多行
>>> obj.close()

   f.write():一次只写一行

 

with管理文件操作:

>>> with open('log','r') as f:    #打开时候无需关闭
...      f.read()
... 
'This is frist line\nThis is second line'

利用上述方法操作配置文件:(只有在2.7以上版本才支持)

>>> with open('log','r') as obj1, open('log1','w') as obj2:
...     for line in obj1:
...         new_line = line.replace('This is frist line','wahaha')
...         obj2.write(new_line)

 作业来了。。。

##############配置文件################
global
        log 127.0.0.1 local2
        daemon
        maxconn 256
        log 127.0.0.1 local2 info
defaults
        log global
        mode http
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms
        option  dontlognull

listen stats :8888
        stats enable
        stats uri       /admin
        stats auth      admin:1234

frontend oldboy.org
        bind 0.0.0.0:80
        option httplog
        option httpclose
        option  forwardfor
        log global
        acl www hdr_reg(host) -i www.oldboy.org
        use_backend www.oldboy.org if www

backend www.oldboy.org
       server  100.1.7.9 100.1.7.9 weight 20 maxconn 30


##############需求################
增删查
1、查
    输入:www.oldboy.org
    获取当前backend下的所有记录

2、新建
    输入:
        arg = {
            'bakend': 'www.oldboy.org',
            'record':{
                'server': '100.1.7.9',
                'weight': 20,
                'maxconn': 30
            }
        }

3、删除
    输入:
        arg = {
            'bakend': 'www.oldboy.org',
            'record':{
                'server': '100.1.7.9',
                'weight': 20,
                'maxconn': 30
            }
        }

需求
修改配置文件练习--结合上述操作+Flag实现
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import time
import os
import json
OldFile="haproxy"      #源文件
Bak_File="haproxy%s"%(time.strftime('%y-%m-%d-%H-%M-%S'))    #备份文件

def Check(arg):
    '''通过设置标签Flag位,将需要检查的内容append到列表中,最后返回'''
    Backend_List = []
    Flag = False
    with open(OldFile,'rb') as f:
        for line in f.xreadlines():
            if line.strip().startswith('backend') and line.strip().split()[-1] == str(arg):
                Flag = True
                continue           #检查到包含backend www.oldboy.org行时,直接中断循环,进入下一行
            if Flag and line.strip().startswith('backend'):
                '''server  100.1.7.9 100.1.7.9 weight 20 maxconn 30的一行或者多行结束,设置Flag为False'''
                Flag = False
            if Flag and line:
                '''当Flag为True时,内容添加到列表中'''
                Backend_List.append(line.strip())
    return Backend_List
#print Check('www.oldboy.org')
def Add(arg):
    '''分为两种情况:一种是不存在对应的backend,此时只需要将backend和对应的record先写入列表中,然后循环列表,追加到新的文件中
    另一种情况是存在对应的backend,此时需要将原有的backend和record和新需要增加的record全部先写入列表中,然后通过循环列表写入到新的文件中'''
    Add_dict = json.loads(arg)
    BackTitle = "backend %s" %(str(Add_dict['backend']))
    BackBody = 'server  %s %s weight %d maxconn %d' %(Add_dict['record']['server'],Add_dict['record']['server'],
                                    Add_dict['record']['weight'],Add_dict['record']['maxconn'],)
    Backend_List = Check(Add_dict["backend"])
    if not Backend_List:
        print "不存在对应的backend"
        Backend_List.append('%s%s'%(BackTitle,'\n'))
        Backend_List.append(BackBody)
        with open(OldFile,'rb') as f_old,open('ha_new','ab') as f_new:
            for line in f_old.readlines():
                f_new.write(line)
            for line in Backend_List:
                if line.strip().startswith('backend'):
                    f_new.write("%s" %line)
                else:
                    f_new.write("%s %s\n" %(" "*6,line))

    else:
        print "存在对应的backend"
        with open(OldFile,'rb') as f_old,open('ha_new','ab') as f_new:
            Flag = False
            Has_Write = False
            Backend_List.insert(0,'%s'%(BackTitle,))
            if BackBody not in Backend_List:
                Backend_List.append(BackBody)
            print Backend_List
            for line in f_old.readlines():
                if line.strip().startswith('backend') and line.strip().endswith(Add_dict['backend']):
                    Flag = True
                    continue
                if Flag and line.strip().startswith('backend'):
                    Flag = False
                if not Flag:
                    f_new.write(line)
                else:
                    if not Has_Write:
                        print Backend_List
                        for record in Backend_List:
                            if record.strip().startswith('backend'):
                                f_new.write("%s\n" %record)
                            else:
                                f_new.write("%s %s\n" %(" "*6,record))
                        Has_Write = True    #必须设置,否则会重复添加内容
    #os.rename(OldFile,Bak_File)
    #os.rename('ha_new',OldFile)
arg = '{"backend": "www.oldboy.org","record":{"server": "100.1.7.9","weight": 20,"maxconn": 30}}'
Add(arg)

def Delete(arg):
    '''删除的思路和上面的相同'''
    '''arg = {
            'bakend': 'www.oldboy.org',
            'record':{
                'server': '100.1.7.9',
                'weight': 20,
                'maxconn': 30
            }
        }'''
    Add_dict = json.loads(arg)
    BackTitle = "backend %s" %(str(Add_dict['backend']))
    BackBody = 'server  %s %s weight %d maxconn %d' %(Add_dict['record']['server'],Add_dict['record']['server'],
                                    Add_dict['record']['weight'],Add_dict['record']['maxconn'],)
    Backend_List = Check(Add_dict['backend'])
    print Backend_List
    if not Backend_List:
        print "\033[32m你需要删除的backend记录不存在\033[0m"
    else:
        Backend_List.insert(0,BackTitle)
        print BackBody
        if BackBody in Backend_List:
            Backend_List.remove(BackBody)
            print "删除指定内容"
        else:
            print "\033[32m你需要删除的backend记录不存在\033[0m"
        print Backend_List
        with open(OldFile,'rb') as f_old,open('ha_new','ab') as f_new:
            Flag = False
            Has_Write = False
            for line in f_old.readlines():
                if line.strip().startswith('backend') and line.strip().endswith(Add_dict['backend']):
                    Flag = True
                    continue
                if Flag and line.strip().startswith('backend'):
                    Flag = False
                if not Flag:
                    f_new.write(line)
                else:
                    if not Has_Write:
                        for record in Backend_List:
                            if record.strip().startswith('backend'):
                                f_new.write("%s\n" %record)
                            else:
                                f_new.write("%s %s\n" %(" "*6,record))
                        Has_Write = True
#Delete(arg)

if __name__ == '__main__':
    print """你想要执行如下哪个操作:
             1、查看
             2、增加
             3、删除
             """
    Chose_Num = int(raw_input("请输入你数字:"))
    arg = '{"backend": "www.oldboy.org","record":{"server": "100.1.7.9","weight": 20,"maxconn": 30}}'
    if Chose_Num == 1:
        print Check('www.oldboy.org')
    elif Chose_Num == 2:
        Add(arg)
    elif Chose_Num ==3:
        Delete(arg)
    else:
        print "\033[31m你输入的数字是无效的\033[0m"
demo

 

posted on 2015-12-24 13:13  阿里山QQ  阅读(292)  评论(0编辑  收藏  举报