python自動化運維之路03

set集合

集合是一個無序的、不可重複的集合。主要做用有:html

1.去重,把一個列表變成集合,就等於去重了。
2.關係測試,測試兩組數據以前的交集、差集、並集等關係python

經常使用操做

建立、交集、並集、差集、對稱差集、子集、父集 長度、判斷元素是否在集合中、刪除linux

 

# 建立集合:
set1 = set([1,2,3,4,5,90])
set2 = set([2,378,98])

# 交集 (在set1和set2中都有的元素)
print(set1.intersection(set2))
print(set1&set2)

# 並 set1和set2的全部元素的集合
print(set1.union(set2))
print(set1|set2)
# 差集 :在set1中不在set2中
print(set1.disfference(set2))
print(set1-set2)
# 對稱差集 項在t或s中,但不會同時出如今兩者中
print(set1^set2)
print(set1.symmetric_difference(set2))
# 子集
print(set1.issubset(set2))
# 父集
print(set1.issuperset(set2))
# 在set中添加一項
print(set1.add(45))
# 在set 中添加多項
print(set1.update(set2))
# remove刪除指定項,若不存在,會報錯
print(set1.remove(2))
print(set1.discard(2))  # remove刪除指定項,如不存在,不報錯
print(set1.pop())  # 刪除任意一項
set1.discard(98)

# 集合的長度
print(len(set1))
x = ''
if x in set1:# 判斷 x是否在set1 中。
    pass
if x not in set1:# 判斷集合不在set1中。
    pass
if set1.issubset(set2): # s <= t 測試是否s中的每個元素都在t中
    pass

文件操做

對文件的操做流程:

1.打開文件,獲得文件句柄並賦值給一個變量
2.經過句柄對文件進行操做
3.關閉文件git

基本操做:

f = open("yesterday",'r',encoding='utf-8')  # 只可讀
f2 =open("yesterday2",'w',encoding="utf-8")  # 可寫,覆蓋原來的內容
f3=open("yesterday2",'a',encoding="utf-8")  # 追加不可讀
data = f.read() # 打印全部內容
f2.write("我愛北京天安門\n")
f2.write("天安門\n")

f4 = open("yesterday","a+",encoding='utf-8')  # 新建文件
print(f4.readline())  #
print(f4.readline())  # 讀一行
print(f4.encoding) # 打印文件句柄的編號方式
print(f4.tell())  # 顯示當前文件句柄的位置
print(f4.seek(10))  # 件句柄調到第10個位置,
# 備註:在寫文件時,若是使用r+ ,w+,時,不使用seek時,在文件末尾追加寫入的內容
#  若使用,seek(),就覆蓋寫入了,不在使用追加模式
f4.truncate(10) # 從文件開頭到10 截斷

f4.flush()  # 將數據由內存刷入到文件或者硬盤
print(f4.readline())
for line in f4:
    print(line)  # 只在內存中保存一行

f5 = open("test.txt",'rb')
print(f5.readline())
f5.close()

打開文件的模式有:

r,只讀模式(默認)。
w,只寫模式。【不可讀;不存在則建立;存在則刪除內容;】
a,追加模式。【可讀; 不存在則建立;存在則只追加內容;】
"+" 表示能夠同時讀寫某個文件shell

r+,可讀寫文件。【可讀;可寫;可追加】
w+,寫讀
a+,同a編程

with語句:

python 2.7中
with open('log','r') as f:
 for line in f:
     print(line)

python3中:
with open('log1') as obj1, open('log2') as obj2:
       pass

編碼方式

在python2中,默認編碼是ASSIC編碼,若在文件中指定文件的編碼方式爲「utf-8",若想轉化成gbk,須要先解碼爲unicode,轉編碼爲gbkjson

例如:windows

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

import chardet
tim = '你好'
print chardet.detect(tim)
#先解碼爲Unicode編碼,而後在從Unicode編碼爲GBK
new_tim = tim.decode('UTF-8').encode('GBK')
print chardet.detect(new_tim)

#結果
'''
{'confidence': 0.75249999999999995, 'encoding': 'utf-8'}
{'confidence': 0.35982121203616341, 'encoding': 'TIS-620'}

  python3中:服務器

在python3中,默認的就是unicode

# author:snate
tim =u"你好"
new_tim = tim.encode('GBK')直接編碼就能夠。
print(new_tim)
new_time=tim.encode("GBK").decode("GBK").encode("GB2312")
print(new_tim)

面向對象、面向過程、函數式編程

面向對象是把構成問題事務分解成各個對象,創建對象的目的不是爲了完成一個步驟,而是爲了描敘某個事物在整個解決問題的步驟中的行爲。
面向過程就是分析出解決問題所須要的步驟,而後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就能夠了。
簡單說,"函數式編程"是一種"編程範式"(programming paradigm),也就是如何編寫程序的方法論。
它屬於"結構化編程"的一種,主要思想是把運算過程儘可能寫成一系列嵌套的函數調用數據結構

函數的基本語法及特徵

定義: 函數是指將一組語句的集合經過一個名字(函數名)封裝起來,要想執行這個函數,只需調用其函數名便可
函數的特徵:
減小重複代碼
使程序變的可擴展
使程序變得易維護

函數的定義:

語法:

def function():
     print("in the function")

還能夠傳遞參數:

def Sum(x,y):
     sum = x +y 
     return sum

形參變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。所以,形參只在函數內部有效。函數調用結束返回主調用函數後則不能再使用該形參變量
實參能夠是常量、變量、表達式、函數等,不管實參是何種類型的量,在進行函數調用時,它們都必須有肯定的值,以便把這些值傳送給形參。所以應預先用賦值,輸入等辦法使參數得到肯定值。

 位置參數和關鍵字參數、默認參數、可變參數

#!/usr/bin/env python 
# _*_ encoding:utf-8 _*_
# author:snate
# 位置參數和關鍵字參數
def test(x,y,z):
    print(x,y,z)
# 默認參數
def test2(sex,name="alex",age=12):
    print(sex,name,age)
# 參數個數不固定的形式參數
def test3(name,*args):
    print(name,args)
def test4(name,**kwargs):
    print(name,kwargs)
test(1,2,3) # 位置參數:實參和形參必須一一對應
test(x=1,y=2,z=2)
test(x=1,z=2,y=2) # 關鍵字參數與位置無關,沒必要一一對應
test2("女",age=25,name=12)  # 默認參數必須放到後面,
test3("gxw",1,1,23,4,["nihao",2,3,5]) #*args 會把多傳入的多個參數變成一個元組形式
test3("gxw",*[1,2,3,4,5]) # *args 會把多傳入的參數變成一個元組形式
test4(name="alex",age=12,sex="f",id=1)  # *kwargs 會把多傳入的關鍵字參數變成一個dict形式
'''
1 2 3
1 2 2
1 2 2
女 12 25
gxw (1, 1, 23, 4, ['nihao', 2, 3, 5])
gxw (1, 2, 3, 4, 5)
alex {'id': 1, 'sex': 'f', 'age': 12}
'''

return

在子程序中定義的變量稱爲局部變量,在程序的一開始定義的變量稱爲全局變量。
全局變量做用域是整個程序,局部變量做用域是定義該變量的子程序。
當全局變量與局部變量同名時:
在定義局部變量的子程序內,局部變量起做用;在其它地方全局變量起做用

#!/usr/bin/env python 
# _*_ encoding:utf-8 _*_
# author:snate
school = "oldboy Edu."
name = "alec"
def test1(name):
    print("修改前:"+name)
    name = "alex"
    print("修改後:"+name)
    global school
    school = "MaGe"
    print(school)

test1(name)
print(school)

備註:爲了在函數中修改全局變量的值,須要global聲明,可是在之後的工做中禁用。

遞歸

在函數內部,能夠調用其餘函數。若是一個函數在內部調用自身自己,這個函數就是遞歸函數

def calc(n):
    print(n)
    if int(n/2) ==0:
        return n
    return calc(int(n/2))
calc(10)
'''
10
5
2
1
'''

 遞歸的特徵:

遞歸特徵:
1. 必須有一個明確的結束條件
2. 每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減小
3. 遞歸效率不高,遞歸層次過多會致使棧溢出(在計算機中,函數調用是經過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。因爲棧的大小不是無限的,因此,遞歸調用的次數過多,會致使棧溢出)

高階函數

變量能夠指向函數,函數的參數能接收變量,那麼一個函數就能夠接收另外一個函數做爲參數,這種函數就稱之爲高階函數

def add(x,y,f):
    return f(x) + f(y)

res = add(3,-6,abs)
print(res)

 做業1:用python實現簡答的sed替換功能

 ReadMe:

這個一個使用python實現簡單sed功能的程序 
 我的介紹 
  name:Gaoxuewu 
 nickName:snate 
 blog_addr: http://www.cnblogs.com/itlinux/p/5749369.html 
 
 項目需求 
 利用python實現shell中的sed的簡單替換功能 
 功能介紹 
  將文件打開,一行一行的讀,判斷每行中,是否存在要替換的字符,若存在就替換 將替換後的行寫入到新的文件;若不存在直接將讀出的行寫入到另外一個文件。 
 
 環境依賴 
  python3.* 
 window/linux os 
 os模塊 
 sys模塊 
 
 目錄結構 
 testSed
├── __init__.py
├── README.md # 程序介紹
├── testSed FlowChart # 程序流程圖
├──yesterday # 須要讀取的文件
├── yesterday.bak  #替換以前,文件的備份
 
 運行說明 
 在搭建好的python環境中,運行python testshell.py "年少輕狂" "Alex 很狂",就能實現用"Alex 很狂"替換"年少輕狂"的功能。 

流程圖:

程序:

#!/usr/bin/env python 
# _*_ encoding:utf-8 _*_
# author:snate
'''
將yesterday文件中的「年少輕狂」替換成「alex 很狂"
'''
from sys import argv
import os
f1 = open("yesterday", "r", encoding="utf-8")
f2 = open("yesterday.bak", "w", encoding="utf-8")
for line in f1:
    if argv[1] in line: #"年少輕狂"
        line = line.replace(argv[1], argv[2]) # "---》alex 很狂"
    f2.write(line)
f1.close()
f2.close()
os.rename("yesterday","yesterday-bak")
os.rename("yesterday.bak","yesterday")

做業2:查找、修改、增長和刪除proxy的內容

 Readme:

# 這個一個關於proxy配置文件增、刪、查的程序

### 我的介紹
* name:Gaoxuewu
* nickName:snate
* email:hangtiangazi@163.com
* blog_addr:http://www.cnblogs.com/itlinux/p/5749369.html

### 功能介紹
* 查詢時,輸入域名,顯示域名的相關的backend的信息
* 刪除時,輸入域名,可以刪除域名以及配置服務器相關的信息
* 增長時,須要輸入配置信息的字典,字典中包含backend的域名信息,以及包含IP,Maxconn,server的record列表
     1.例如:輸入內容爲:修改需輸入內容舉例:{"backend": "test.oldboy.org","record":{"server": "100.1.7.9","weight": 20,"maxconn": 30}}
     程序會自動判斷輸入的格式是否正確,若不正確,提示用戶從新輸入,直到輸入正確的格式。 
     2.根據輸入的內容的backend的域名,判斷域名是否不在,不存在,添加域名,和須要配置的服務器信息;
     3.若域名存在,判斷域名的服務器信息是否存在,若不在提供用戶信息已存在,不須要修改文件;若不存在,
       在域名信息後面增長該信息。
       
### 環境依賴:
* python3以上版本
* linux/windows os 
* sys 模塊
* os 模塊
* time模塊 

###目錄結構:
    testProxy
    ├── __init__.py
    ├── README.md # 程序介紹
    ├── testProxy FlowChart # 程序流程圖
    ├──proxy # proxy 配置文件
    ├── proxy.bak_.... proxy的備份文件
    ├── proxy.log # 日誌文件
    ├── tetsProxy.py # 程序
       ├──search_backend(search_domain_name) # 查找域名信息
       ├──input_format(add_domain_info_str) # 判斷輸入域名及服務器的配置信息是否正確
       ├──add_backend() # 添加域名信息
       ├──dek_backend(del_domain_name) # 刪除域名相關信息
       ├──main() #主程序
  
### 運行說明
在搭建好的python環境中,運行python testProxy.py 便可。

  程序流程圖:

程序:

#!/usr/bin/env python
# _*_ encoding:utf-8 _*_
# author:snate
# 經過域名查詢proxy的函數
import json
import time
import os
time_fort1 = "%Y-%m-%d %H:%M:%S"
time_fort2 = "%Y-%m-%d-%H-%M-%S"
current_time = time.strftime(time_fort1)
bak_time = time.strftime(time_fort2)
# 查找函數,根據輸入的域名,返回域名的詳細信息
def search_backend(search_domain_name):
    '''
    :param : Domain name
    :return: the specific information of Daomain ,Fomat:list
    '''
    f = open("proxy",'r',encoding="utf-8")
    info_list=[]
    Flag = 0 # 設置標誌位 默認值爲0 表示爲匹配
    for line in f:
        line = line.strip() # 去掉兩端的空格和換行
        if line == "backend %s" % search_domain_name:
            Flag = 1 # 若匹配上默認值爲1
        elif line.startswith("backend"):
            Flag = 0
        elif Flag == 1 and  len(line) != 0: # 接着循環,將doamain的信息保存到info_list中。
            info_list.append(line)
    f.close()
    return info_list
# 判斷輸入的的域名信息及服務器的配置信息是否正確
def input_format(add_domain_info_str):
    '''
    :param add_domain_info_str:
    :return: boolean
    '''
    add_domain_content = json.loads(add_domain_info_str)
    try:
        add_domain_name = add_domain_content["backend"]
        add_domain_server = add_domain_content["record"]["server"]
        add_domain_weight = add_domain_content["record"]["weight"]
        add_domain_maxconn = add_domain_content["record"]["maxconn"]
    except:
        return False
    else:
        return True
# 添加域名信息
def add_backend():
    '''
    :return: None
    '''
    while True:
        add_domain_info_str = input("請輸入用戶要增長的配置信息:")
        Fort_Flag = input_format(add_domain_info_str)
        if Fort_Flag :
            add_domain_content = json.loads(add_domain_info_str)
            add_domain_name = add_domain_content["backend"]
            add_domain_server = add_domain_content["record"]["server"]
            add_domain_weight = add_domain_content["record"]["weight"]
            add_domain_maxconn = add_domain_content["record"]["maxconn"]
            add_domain_server_info = "server %s %s weight %s maxconn %s "%(add_domain_server,add_domain_server,\
                                    add_domain_weight,add_domain_maxconn)
            info_list = search_backend(add_domain_name)
            if len(info_list) == 0:
                with open("proxy","r",encoding="utf-8") as proxy_read, \
                        open("new_proxy","w",encoding="utf-8") as proxy_bak_write:
                    content_list = proxy_read.readlines()
                    content_list.append("\n")
                    content_list.append("backend %s\n" %add_domain_name)
                    content_list.append("%s %s" % (8*" ", add_domain_server_info))
                    proxy_bak_write.writelines(content_list)
                # 提示用戶沒有域名信息,將配置信息添加到配置文件最後
                print("No domain name,We will add to the end of the proxy!")
                time.sleep(1)
                print('''\033[31;1mInformation has been added successly!!!!\033[0m''')
                os.rename("proxy","proxy.bak_%s" % bak_time)
                os.rename("new_proxy", "proxy")
                with open("proxy.log", 'a+',encoding='utf-8') as log_write:
                    log_write.write("%s ad d the %s into proxy config successfully!\n" %(current_time,add_domain_server_info))
            else:
                if add_domain_server_info in info_list: # 若服務器信息重疊,提示用戶信息重疊,不須要配置文件
                    print("\033[31;1mServer_info:%s is existed!,don't need add!!!!\033[0m" % add_domain_server_info)
                else:
                    info_list.append(add_domain_server_info)
                    with open("proxy", 'r', encoding='utf-8') as proxy_read, \
                          open("proxy_bak", 'w', encoding='utf-8') as proxy_bak_write:
                        begin_Flag = 0  # 設置獲取目標內容的flag標誌
                        end_Flag = 0  # 設置限制目標內容循環的標誌
                        for line in proxy_read.readlines():
                            if line.strip() == "backend %s" % add_domain_name:  # 若其中一行的內容爲「backend domain_name",更改獲取內容表示符的值爲1
                                begin_Flag = 1
                            # 更改獲取表示符以後,繼續循環表示列表,若碰到以「backend」開頭的行,從新將開始標誌位設置爲0
                            elif line.strip().startswith("backend"):
                                begin_Flag = 0
                            if begin_Flag == 0: # 若獲取內容的表示符爲0 表示非目標內容,直接寫入到proxy_bak文件。
                                proxy_bak_write.writelines(line);
                            elif begin_Flag == 1 and end_Flag == 0:
                                proxy_bak_write.write("backend %s\n" % add_domain_name)
                                for index,domain_info in enumerate(info_list):
                                    info_list[index] == '%s%s\n'%(8*" ",domain_info)
                                proxy_bak_write.writelines(info_list)
                                proxy_bak_write.write('\n')  # 最後加一個空白行
                                end_Flag = 1  # 設置限制目標內容表示符爲1
                        os.rename("proxy", "proxy.bak_%s" % bak_time)
                        os.rename("proxy_bak", "proxy")
                        with open("proxy.log", "a+",encoding='utf-8') as log_write:
                            log_write.write("%s add the %s into %s proxy config\n" % (current_time, add_domain_server_info,\
                            add_domain_name))
            break
    else:
        print("您輸入的格式不正確,請從新輸入!")
# 刪除域名信息
def del_backend(del_domain_name):
    '''
    :param del_domain_name:
    :return: None
    '''
    with open("proxy", 'r', encoding='utf-8') as proxy_read, \
            open("proxy_bak", 'w',encoding='utf-8') as proxy_bak_write:
        begin_Flag = 0
        for line in proxy_read.readlines():
            line = line.strip()
            if "backend %s" %del_domain_name == line:
                begin_Flag == 1
            elif line.startswith("backend"):
                begin_Flag = 1
            if begin_Flag == 0 :
                proxy_bak_write.write(line)
    with open("proxy.log",'a+',encoding='utf-8') as log_write:
        log_write.write("%s del the %s info!\n"% (current_time, del_domain_name))
    os.rename("proxy","proxy.bak_%s" %(bak_time))
    os.rename("proxy.bak","proxy")
    print("%s's info is successfully deleted!" % del_domain_name)
# 主程序
def main():
    '''

    :return: none
    '''
    while True:
        print('''
        1.查詢
        2.增長
        3.刪除
        4.退出
        ''')
        user_choose = input("請輸入您的選擇:")
        if user_choose.isdigit():
            user_choose = int(user_choose)
            if user_choose == 1:
                search_domain_name = input("請輸入您要查詢詳細的域名:")
                info_list = search_backend(search_domain_name)
                if len(info_list) == 0:
                    print("The info of %s don't exist" % search_domain_name)
                else:
                    for line in info_list:
                        print('\033[31;1m%s\033[0m' % line)
            elif user_choose == 2:
                add_backend()
            elif user_choose == 3:
                del_domain_name = input("input the domain name you want to delete:")
                info_list = search_backend(del_domain_name)
                if len(info_list) == 0:
                    print("要刪除的域名信息不存在,不執行任何操做!")
                else:
                    del_backend(del_domain_name)
            elif user_choose == 4:
                for i in range(3):
                    print("程序在\033[31;1m[%s]\033[0m秒後退出!" % (3-i))
                    time.sleep(1)
                exit()
        else:
            print("您的輸入有誤,請從新輸入:")
main()
相關文章
相關標籤/搜索