1.面向對象
1.1 異常處理(異常、斷言、異常類型、拋出異常、Python異常捕捉)
異常處理
name = "aa"
try: # 這一段是要執行的主體
print(name)
# except Exception as msg: # 如果沒有正常執行,就執行下面的這一段。Exception 是錯誤類型。
except : # 如果沒有正常執行,就執行下面的這一段。Exception 是錯誤類型(有好多類型,可以百度查下,錯誤類型 ,儘量寫的準確些)。
print("name is err...")
else: # 只有當try的那段 正常執行了後,纔會執行下面的這一段。
print("welcome: {}.".format(name))
finally: # 無論有沒有正常執行 都會執行這一段的。
print("this is test.")
斷言 assert
格式: assert 表達式, '異常錯誤信息'
# 當表達式不成立時,就會拋後面的錯誤信息。
assert name == "aa","name not wf"
raise 異常類型("錯誤提示") ;和try結合使用
作用:
1.捕獲異常爲了讓程序不至於中斷,在邏輯控制之內。
2.拋出異常是爲了,保證程序在遇到這種問題的時候必須中止。
v1 = "wf"
li = [1,23]
try:
# print(v1)
# print(li[4])
raise IndexError("索引不存在") # 一般不用
# 爲啥寫這麼多except呢?方便記錄日誌.
except IndexError as msg: # 錯誤類型是索引
print(msg)
except Exception as msg: # 所有的錯誤類型,你可以這麼些
print(msg)
else:
print("good")
finally:
print("test")
1.2 面向對象編程(面向對象基礎、封裝和調用、間接調用、定義類、類成員)
def send_mail(msg,mail):
print("msg:{} to mail:{}".format(msg,mail))
send_mail("hellow","[email protected]")
class mail():
def __init__(self,msg,mail):
#構造方法,無須調用,自動執行
self.msg = msg
self.mail = mail
def send_mail(self):
print("send msg:{} to mail:{}".format(self.msg, self.mail))
# 創建一個對象,obj 就是對象。obj是類對象的指針。
obj = mail("hello","[email protected]") 他指向mail這個類。
obj.send_mail()
什麼時候能用到類呢? 我個人理解:
例如我寫一個zabbix 增刪改查腳本,每次操作都需要使用zabbix創建好的這個連接。
我當然可以寫成面向過程或面向函數的這種腳本。但是它的可讀性和代碼的簡潔度不好。
我寫成一個類,無論是使用還是可讀性都會變的很好。
1.3 繼承與多態(類的繼承、繼承順序、方法重寫)
class c1(): # 父類;基類
def f1(self):
v1 = 1
print(v1)
def f2(self):
v2 = 2
print(v2)
class c2(c1): # 子類;派生類,如何繼承多個父類呢? c2(c1,c4)
name = "wangfei" # 靜態字段
def __init__(self,age):
self.age = age
def f1(self):
v1 = "c2_2" # 普通字段
print(v1)
def f3(self):
v3 = 3
print(v3)
# obj = c2("18") #
# # obj.f1() # 子類的方法是優先父類的方法
# # obj.f2() # 子類沒有這個方法就到父類去找
# re = c2.name # 靜態字段通過類來訪問的
# print(re)
# re2 = obj # 普通字段通過對象來訪問
# print(re2)
啥叫多態呢? 可以往類裏傳入任何數據類型的參數。
多繼承注意事項。
1. 當只有一條道的時候,就是一條路走到底。子類繼承父類,父類繼承父父類。
2. 當有2條道的時候,左邊的的優先於右邊的。當左邊的道走到第三步還沒有走到時,就要返回同級走第二條道到底了。
3. 這裏需要注意的是,self是代表是第一層的obj 就是最小的那代類。
1.4 類方法與類屬性(類方法定義、方法調用、類內置屬性、運算符重載)
類的方法
class c1():
v2 = 20
def __init__(self,v1): # 構造方法
self.v1 = v1
def f1(self): # 普通方法
print(self.v1)
print(c1.v2)
@staticmethod
def f2(): # 靜態方法,通過類來調用;爲了節省內存
print(c1.v2)
obj1 = c1(120)
c1.f2() # 通過類來訪問靜態方法
obj1.f2() # 通過對象來訪問
類的屬性
class c1():
v2 = 20
def __init__(self,v1):
self.v1 = v1
def f1(self):
print(self.v1)
print(c1.v2)
@property # 這個就叫做屬性.
def f2(self):
print(c1.v2)
def f3(self):
re = obj1.f2
# print(re)
obj1 = c1(120)
obj1.f2 # 奇怪吧? 通過訪問字段的方式進行使用的
2.實戰應用
2.1 模塊應用Requests(RESTAPI標準操作、HTTP請求與返回操作、API接口調用實戰)
獲取訪問url的狀態碼
import requests
res = requests.get("http://www.baidu.com/")
print(res.status_code)
案列1:讀取url列表,進行測試,如果狀態碼是40x 50x 的就打印出來。生產環境就是調用接口進行報警。
import requests
url_list = ['http://www.baidu.com', 'http://www.sina.com.cn', 'http://adminset.cn']
err_http_code = [401,402,403,404,500,501,502,503,504,505]
for url in url_list:
res = requests.get(url)
if res.status_code in err_htttp_code:
print("access {} http code failed".format(url))
案例2:上方案例從文件中讀取url列表,進行判斷。
import requests
error_code_list = [401,402,403,404,500,501,502,503,504,505]
with open("url_list.txt","rb") as url_file:
while True:
url_line = url_file.readline()
if url_line:
str_url_line = str(url_line,encoding="utf-8")
str_url = str_url_line.split("\n")[0] # 從文件裏面讀取的行,後面是有換行符的。\n的 不能直接使用,需要去掉哦。
res = requests.get(str_url)
if res.status_code in error_code_list:
print("url: {}, status code: {}".format(str_url,res.status_code))
else:
break
如果url是包含https,怎麼處理呢 ?
res = requests.get("https://www.12306.cn",verify = False)
print(res)
請求api接口,獲取添加的主機信息。由於請求的時候,需要token信息,url需要拼接下。
# url後面的”“ 表示後面要接參數 ,因爲在字典裏面定義了(para變量),requests模塊加了params後會自動進行 拼接得。
# http://115.28.147.154/cmdb/get/host/?token="token信息"&name=“user”
para = {'token': 'PnSlpwJDQE3L', 'name': 'adminset'}
res = requests.get("http://115.28.147.154/cmdb/get/host/", params = para)
# 查看拼接後的url
print(res.url)
# 獲取結果
data = r.text
import json
# 進行反序列化
d1 = json.loads(data)
print(d1['data']['ip'])
2.2 模塊應用Redis、MySQL、MongoDB
向redis裏面寫入數據,讀取數據。
import redis
redis_conn = redis.StrictRedis(host="127.0.0.1",port=6379,db=0)
redis_conn.set("name","wangfei") # 寫入數據
re = redis_conn.get("name") # 讀取數據數據
print(re)
redis_conn.lpush("list2","python class") # push的是一個列表
例子:獲取主機名和ip地址 ,然後寫到redis裏面去。
import redis
import socket
def get_sys_info():
try:
hostname = socket.gethostname()
ip = socket.gethostbyname(hostname)
except Exception as msg:
print(msg)
hostname = ""
ip = ""
finally:
data = {"hostname": hostname,"ip":ip}
return data
# 鏈接redis
redis_conn = redis.StrictRedis("127.0.0.1",6379)
try:
# 獲取系統信息
re = get_sys_info()
# 將系統信息寫到redis,作爲列表裏的一個元素。
redis_conn.lpush("host",re)
except Exception as msg:
print(msg)
# 上面這一段或者是這麼寫。
# re = get_sys_info()
# assert redis_conn.lpush("host",re),"lpush error"
2.3 模塊應用logging(日誌記錄,爲自己的程序添加日誌)
Level | Numeric value |
---|---|
CRITICAL | 50 |
ERROR | 40 |
WARNING | 30 |
INFO | 20 |
DEBUG | 10 |
import logging
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
datefmt='%Y%m%d %H:%M:%S',
filename="./agent.log",
filemode='a')
log = "redis connecting+++++++++++++"
logging.critical(log)
2.4 模塊應用psutil(操作系統信息採集實戰)
psutil 模塊獲取系統信息
import psutil
# 獲取cpu的數量信息
print(psutil.cpu_count()) # 邏輯核心數
print(psutil.cpu_count(logical=False)) # 物理核心數
# 獲取所有磁盤分區信息
# print(psutil.disk_partitions())
res = psutil.disk_partitions()
for mount in res:
print(mount[1])
# 獲取磁盤分區的使用信息
# print(psutil.disk_usage("/"))
res = psutil.disk_partitions()
for mount in res:
print(psutil.disk_usage(mount[1]))
# 獲取內存信息
print(sutil.virtual_memory())
print(sutil.virtual_memory().total)
2.5 模塊應用configparser(配置文件解析,爲自己的程序增加配置文件管理)
configparser 模塊讀取配置文件。
import configparser
# 如何從一個文件裏面讀取參數?
# 讀取文件流程
# 第1步 初始化模塊(我自己想的,幫助記憶理解)
config = configparser.RawConfigParser()
# 第2步 打開配置參數文件
redis_conf_file = open("redis.conf","r")
# 第3步 讀取所有參數內容
config.read_file(redis_conf_file)
# 第4步 獲取對應key下面的參數。
print(config.get("redis","host"))
print(config.get("redis","port"))
-----------------------
備註:redis.conf內容
[redis]
host = 127.0.0.1
port = 6379
例子: 從配置文件裏面讀取redis 地址和端口信息,然後寫一個信息到redis裏面去。
import redis
# python2 python3 導入configparser模塊名不一樣。
try:
import configparser
except Exception as msg:
print(msg)
import ConfigParser
config = configparser.RawConfigParser()
# 打開配置文件,讀取內容
try:
with open("redis.conf","r") as redis_conf_file:
config.read_file(redis_conf_file)
host = config.get("redis","host")
port = config.get("redis","port")
except Exception as msg:
print(msg)
# 寫信息到redis裏面去
try:
redis_conn = redis.StrictRedis(host,port,0)
redis_conn.set("test_key","test_values")
except Exception as msg:
print(msg)
2.6 模塊應用schedule(Python計劃任務實戰)
# 定時任務模塊
# time.sleep 是整個腳本程序都中斷了,任務是串行的。使用schedule 是異步執行的。
import schedule
import time
import threading
def hello(): 60s
print("2 hello")
def morning(): 3600s
print("1 morning")
def job_thread(func): # 多線程
t = threading.Thread(target=func)
t.start()
schedule.every(2).seconds.do(job_thread, hello) # 每隔2秒執行一次任務。
schedule.every(1).seconds.do(job_thread, morning) # 每隔1秒 執行一次任務。
while True: # 這個是固定的寫法,每隔1s 檢查查定時任務
schedule.run_pending()
time.sleep(1)
2.7 xlrd/xlwt (實現對excel文件的讀寫)
import xlrd # 讀取excel文件內容
#### 從Excel文件讀取內容
zabbix_file = xlrd.open_workbook("./zabbix-host.xls")
zabbix_file_table = zabbix_file.sheet_by_name("sheet01")
print(zabbix_file_table.nrows) # 獲取行數
print(zabbix_file_table.row_values(0)) # 獲取指定行的內容
print( zabbix_file_table.ncols) # 獲取列數
print(zabbix_file_table.col_values(2)) # 獲取指定列的內容
print(zabbix_file_table.cell(1,2)) # 獲取1行2列內容
#### 向Excel文件寫入內容
import xlwt # 向Excel文件裏寫入內容
zabbix_file = xlwt.Workbook(encoding="ascii") # 指定編碼
file_sheet = zabbix_file.add_sheet("sheet02") # 新建工作簿
file_sheet.write(0,1,label = "hehe") # 寫入內容
file_sheet.write(0,2,label = "hehe")
file_sheet.write(0,4,label = "hehe")
file_sheet.write(0,3,label = "hehe")
zabbix_file.save("test.xls") # 保存
3.實戰案例
3.1 調用Zabbix API ,增刪改主機。
from pyzabbix import ZabbixAPI
import xlrd
import configparser
import logging
import sys
import os
class zabbix():
def __init__(self,host_file):
self.host_file = host_file
# 日誌模塊
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
datefmt='%Y%m%d %H:%M:%S',
filename="./zabbix.log",
filemode='a')
# 讀取zabbix 配置文件
try:
config = configparser.RawConfigParser()
with open("/Users/feiwang/PycharmProjects/python-study2/work/zabbix.conf","r") as zabbix_conf_file:
config.read_file(zabbix_conf_file)
self.zabbix_user = config.get("zabbix","user")
self.zabbix_passwd = config.get("zabbix","passwd")
except Exception as msg:
logging.error(msg)
raise msg
# 登錄zabbix
try:
self.zapi = ZabbixAPI("http://192.168.4.135/zabbix")
self.zapi.login(self.zabbix_user,self.zabbix_passwd)
logging.info("connecting zabbix successful.")
except Exception as msg:
logging.error("connecting zabbix failed" + "detail:{}".format(msg))
raise msg
def load_zabbix(self):
# 讀取excel文件
try:
zabbix_file = xlrd.open_workbook(self.host_file)
zabbix_file_table = zabbix_file.sheet_by_name("sheet01")
logging.info("open host.xls ok.")
except Exception as msg:
logging.error(msg)
zabbix_file = ''
zabbix_file_table = ''
# 讀取zabbix 信息
host_list = []
for row in range(1, zabbix_file_table.nrows):
row_values = zabbix_file_table.row_values(row)
visible_name = row_values[1]
hostname = row_values[0]
port = row_values[-1]
ip = row_values[-2]
group_id = "2"
create_host = {
"host": hostname,
"description": visible_name,
"name": visible_name,
"interfaces": [
{
"type": 1,
"main": 1,
"useip": 1,
"ip": ip,
"dns": "",
"port": port
}, ],
"groups": [{
"groupid": group_id
}, ], }
host_list.append(create_host)
return host_list
def add_host(self):
for host in self.load_zabbix():
try:
self.zapi.host.create(host)
logging.info("create status: ok, create host info:{}".format(host))
except Exception as msg:
print(msg)
logging.error("zabbix create hosts failed. {}".format(msg))
# # del host
def del_host(self):
'''
循環zabbix 上獲取到的主機,然後和本地excel文件裏要刪除的主機進行對比,如果是的,那麼就把他刪掉。
刪除用hostid
:return:
'''
for host in obj.zapi.host.get():
for del_host in self.load_zabbix():
if host["host"] == del_host["host"]:
try:
self.zapi.host.delete(host["hostid"])
print("delete host{} is ok.".format(host["host"]))
logging.info("del host:{} ok".format(host["hostid"]))
except Exception as msg:
print(msg)
logging.error("del host:{} failed,".format(host["host"]))
if __name__ == "__main__":
action,file = sys.argv[1:]
assert os.path.exists(file),"file:'{}' doesn't exists".format(file)
obj = zabbix(file)
if action == "add":
obj.add_host()
elif action == "del":
obj.del_host()
elif action == "update":
pass
elif action == "get":
pass
else:
print("action is err.")
raise Exception
3.2 開發一個Agent,採集系統信息。
要求:
- 獲取cpu 內存 磁盤(磁盤使用信息) 主機名 主機ip地址 等信息
- 組裝成json格式上傳到redis裏。
- 要求記錄日誌
- 定時執行每10分鐘更新一次。
- 用多線程執行
Agent腳本內容
import json
import platform
import schedule
import psutil
import configparser
import redis
import logging
import threading
import socket
import time
import math
def log():
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s', # 日誌格式
datefmt='%Y%m%d %H:%M:%S', # 時間格式
filename="./agent.log", # 日誌文件的路徑
filemode='a') # 文件的打開模式
return logging.basicConfig
log()
def get_sys():
try:
hostname = socket.gethostname()
ip = socket.gethostbyname(hostname)
except Exception as msg:
print(msg)
hostname = ""
ip = ""
data = {"hostname":hostname,"ip":ip}
return data
def get_cpu():
cpu_count_logical = psutil.cpu_count(logical=False)
cpu_count_phycial = psutil.cpu_count(logical=True)
cpu_percent = psutil.cpu_percent(interval=2)
data = {"phycial_count":cpu_count_phycial,"logical":cpu_count_logical,"percent":cpu_percent}
return data
def get_mem():
# math.ceil(小數) 取整數
mem_total = math.ceil(psutil.virtual_memory().total /1024/1024/1024)
mem_percent = psutil.virtual_memory().percent
data = {"mem_total":mem_total,"mem_percent":mem_percent}
return data
def get_disk():
disk_list = []
all_disk_part = psutil.disk_partitions()
for partition in all_disk_part:
mount_point = partition[1]
mount_total = math.ceil(psutil.disk_usage(mount_point).total/1024/1024/1024)
mount_percent = psutil.disk_usage(mount_point).percent
data = {"mount": mount_point,"total":mount_total,"percent":mount_percent}
disk_list.append(data)
return disk_list
def thread_run():
pass
def agent_info():
sys_data = {}
sys_data["host"] = get_sys()
sys_data["disk"] = get_disk()
sys_data["mem"] = get_mem()
sys_data["cpu"] = get_cpu()
return json.dumps(sys_data) # 進行反序列化
def put_redis():
config = configparser.RawConfigParser()
try:
with open("redis.conf","r") as redis_conf_file:
config.read_file(redis_conf_file)
redis_host = config.get("redis","host")
redis_port = config.get("redis","port")
except Exception as msg:
redis_host = "127.0.0.1"
redis_port = 6379
print(msg)
try:
logging.info("connect redis server.")
redis_conn = redis.StrictRedis(redis_host,redis_port,0)
logging.info("put systeminfo to redis server.")
redis_conn.lpush("host",xagent_info())
logging.info("data:{}".format(agent_info()))
logging.info("put successful....")
def thread_job(func):
target =threading.Thread(target=func)
target.start()
if __name__ == "__main__":
schedule.every(2).seconds.do(thread_job,put_redis)
while True:
schedule.run_pending()
time.sleep(1)