1. 程式人生 > >shelve模組,sys模組,logging模組

shelve模組,sys模組,logging模組

1.shelve模組

  用於序列化的模組,shelve模組比pickle模組簡單,只有open函式,返回類似字典的物件,可讀可寫;key必須為字串,而值可以是python所支援的資料型別.
import shelve
s=shelve.open('a.txt')
s['name']='henry'
s['dic']={'age':18}
print(s['dic'])
shelve模組只有一個函式,就是open用於開啟一個檔案.
開啟以後,操作方法與字典完全一致,你可以把他當成字典,而且自帶buff的字典,可以字典給完成序列化.
該模式序列化得到的資料,只能被該模組使用,其他語言沒有這個模組,所以無法使用,即無法跨平臺.
當你寫的程式是一個單機程式時可以考慮.
後期只要涉及到資料交換就應該用json.

2.sys模組

sys模組是system的縮寫,表示系統
注意:
os operation system 指的是作業系統
而sys指的是python直譯器

import sys
用於接受作業系統呼叫直譯器時傳入引數
sys.path 返回模組的搜尋路徑,初始化時使用PYTHONPATH環境變數的值

sys.argv 用於接受作業系統呼叫直譯器時傳入的引數
當你要開發一款基於CMD的程式時,就需要使用這個屬性了,因為一些作業系統沒有介面,只能通過CMD來使用.
# 需求 開發一個基於CMD的複製檔案的工具
# 第一個引數表示被執行的py檔案 第二個作為原始檔路徑 第三個作為目標檔案的路徑
#
# source_path = sys.argv[1]
# target_path = sys.argv[2]
#
# print(source_path)
# print(target_path)
#
#
# with open(source_path,"rb") as f:
  # with open(target_path,"wb") as f1:
    # while True:
      # data = f.read(1024)
      # if not data:
        # break
      # f1.write(data)

sys.exit(n) 退出程式,正常退出時exit(0)
sys.version 獲取Python解釋程式的版本資訊
sys.platform 返回作業系統平臺名稱

總結:sys 處理與python直譯器相關的一些操作
常用有兩個:sys.path 新增環境變數
sys.argv 獲取呼叫直譯器引數

3.logging模組

翻譯為日誌記錄
該模組就是用於記錄日誌的

日誌是什麼?
日誌就是日記,用於記錄在某個時間點,發生了什麼事

為什麼要記錄日誌?
是為了日後來複查,提取有用的資訊

如何來記錄日誌?
可以直接開啟檔案往裡面寫東西
直接寫入檔案的兩個問題
1.你寫的資料格式別人看不懂
2.解析資料麻煩
因此logging就誕生了

簡單的使用
import logging
logging.debug('這是一條日誌資訊')#沒有輸出任何內容
因為logging模組為日誌劃分了級別,由於你輸出的級別沒有的達到最低級別所以沒有輸出
為什麼要設定最低等級 因為某些級別的日誌,對我是無用的

日誌級別.從低到高分別是:
1.debug 除錯資訊(用於記錄程式設計師在開發過程中的除錯記錄)
2.info 記錄普通訊息(沒有特別的意義,就是簡單的記錄)
3.warning 警告資訊(當某些操作 可能發生錯時,就記錄為警告資訊,涉及一些敏感操作時)
4.error 錯誤資訊(當程式遇到錯誤時)
5.critical 嚴重錯誤 (當程式遇到問題,無法繼續執行時)
logging用數字來表示級別從低到高 0 10 20 30 40 50
為什麼分級別,隨著時間的推移,你的日誌會越來越多,成千上萬條,這個時候提取有用資訊就很慢,所以分等級,這樣一來在檢視日誌的時候,可以快速定位到想要的日誌.

logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
#預設情況下,級別為warning,輸出的位置為控制檯,預設的格式為 級別:日誌生成器名稱:除錯的詳細資訊

#如何修改預設的行為
可在logging.basicConfig()函式中通過具體引數來更改logging模組預設行為,可用引數有
filename:用指定的檔名建立FiledHandler(後邊會具體講解handler的概念),這樣日誌會被儲存在指定的檔案中。
filemode:檔案開啟方式,在指定了filename時使用這個引數,預設值為“a”還可指定為“w”。
format:指定handler使用的日誌顯示格式。
datefmt:指定日期時間格式。
level:設定rootlogger(後邊會講解具體概念)的日誌級別
stream:用指定的stream建立StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者檔案,預設為sys.stderr。若同時列出了filename和stream兩個引數,則stream引數會被忽略。
#format格式
%(name)s:Logger的名字,並非使用者名稱,詳細檢視
%(levelno)s:數字形式的日誌級別
%(levelname)s:文字形式的日誌級別
%(pathname)s:呼叫日誌輸出函式的模組的完整路徑名,可能沒有
%(filename)s:呼叫日誌輸出函式的模組的檔名
%(module)s:呼叫日誌輸出函式的模組名
%(funcName)s:呼叫日誌輸出函式的函式名
%(lineno)d:呼叫日誌輸出函式的語句所在的程式碼行
%(created)f:當前時間,用UNIX標準的表示時間的浮 點數表示
%(relativeCreated)d:輸出日誌資訊時的,自Logger建立以 來的毫秒數
%(asctime)s:字串形式的當前時間。預設格式是 “2003-07-08 16:49:45,896”。逗號後面的是毫秒
%(thread)d:執行緒ID。可能沒有
%(threadName)s:執行緒名。可能沒有
%(process)d:程序ID。可能沒有
%(message)s:使用者輸出的訊息

import logging
logging.basicConfig(filename='mylog.txt', #指定的日誌檔名
         filemode='a', #指定檔案開啟的模式.通常為a
         level=logging.DEBUG, #指定級別
         format='%(filename)s %(levelname)s \
         %(asctime)s %(message)s') #指定現實格式
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')

如果我們需要更詳細的去定製logging的各項功能,就需要系統的瞭解logging的模組
四種核心角色
  1.Logger 日誌的生成器 負責產生一條完整的日誌
  2.Filter 過濾器 負責對日誌進行過濾
  3.Handler 處理器 負責將日誌輸出到指定的位置
  4.Formater 格式化 負責處理日誌顯示格式
一條日誌的生命週期:
1.由Logger產生日誌
2.交給過濾器進行過濾
3.交給Handler按照Formater的格式進行輸出
這三個都可以可以對日誌進行刪選,什麼樣的需要顯示,什麼樣的不需要顯示

#需求:有一個登入註冊程式,功能 需要記錄使用者的操作日誌,程式設計師需要看到最詳細的資訊,而boss只要看到簡單的操作資訊.

#基礎版本:
#自定四種核心角色完成日誌的輸出
import logging
#生成器
mylog=logging.getLogger('mylog') #引數指定生成器的名字(因為可以同時存在多個生成器,需要用名字區分
mylog.setLevel(10) #設定生成器的級別 低於該級別的不會產生

#過濾器這裡不講!需要使用面向物件的基礎知識點!(不常用)

#處理器
handler=logging.FileHandler('youlog.txt',mode='a',encoding='utf-8',delay=False)

#格式化處理器
formater=logging.Formatter(fmt='%(filename)s %(levelname)s %(asctime)s %(message)s')

#將處理器繫結給生成器,add函式表明了一個生成器可以新增多個處理器
mylog.addHandler(handler)

#將格式化處理器繫結給 handler,set函式表明一個處理器只能繫結一個格式化處理器
handler.setFormatter(formater)

mylog.debug('debug')
mylog.info('info')
mylog.warning('warning')
mylog.error('error')
mylog.critical('critical')

#升級版本 按照不同格式輸出到不同檔案中
import logging
#生成器
mylog=logging.getLogger('mylog') #引數指定生成器的名字(因為可以同時存在多個生成器,需要用名字區分
mylog.setLevel(10) #設定生成器的級別 低於該級別的不會產生

#過濾器這裡不講!需要使用面向物件的基礎知識點!(不常用)

#處理器
#給程式設計師看的處理器
handler1=logging.FileHandler('youlog.txt',mode='a',encoding='utf-8',delay=False)
#給老闆看的處理器
handler2=logging.FileHandler('bosslog.txt',mode='a',encoding='utf-8',delay=False)

#格式化處理器
#程式設計師
formater1=logging.Formatter(fmt='%(funcName)s %(module)s %(filename)s\
%(threadName)s %(levelname)s %(asctime)s %(message)s')
#老闆
formater2=logging.Formatter(fmt='%(levelname)s %(asctime)s %(message)s')

#將處理器繫結給生成器,add函式表明了一個生成器可以新增多個處理器
mylog.addHandler(handler1)
mylog.addHandler(handler2)

#將格式化處理器繫結給 handler,set函式表明一個處理器只能繫結一個格式化處理器
handler1.setFormatter(formater1)
handler2.setFormatter(formater2)

mylog.debug('debug')
mylog.info('info')
mylog.warning('warning')
mylog.error('error')
mylog.critical('critical')

 

#現在需求已經實現,但是每次日誌都要寫一堆程式碼,最好能把配置寫死,直接複製資訊
#字典配置logging(重點)
字典的內容重點,但是不需要背
記住的是如何來載入
#logging.config 專門用來配置logging模組
import logging.config

#匯入包含配置字典的模組
import loggin_config

loggin_config在另一個py檔案中:
import logging
# 定義三種日誌輸出格式 開始
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]' #其中name為getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
# 定義日誌輸出格式 結束
logfile_path='配置檔案路徑'
# log配置字典
LOGGING_DIC = {
  'version': 1,
  #是否禁用已存在的生成器,這個值保持為False
  'disable_existing_loggers': False,
  #四個key不能隨便寫 是固定的
  'formatters': {
    #standard 表示格式化的處理器的名字,相當於變數的名字 可以隨便寫
    'standard': {
      #format是固定的不能隨便寫
      'format': standard_format
    },
    'simple': {
      'format': simple_format
    },
  },
  'filters': {},
  'handlers': {
    #列印到終端的日誌
    #console是處理器的名稱可以隨便寫
    'console': {
      'level': 'DEBUG',
      'class': 'logging.StreamHandler', # 列印到螢幕
      'formatter': 'simple'
  },
    #列印到檔案的日誌,收集info及以上的日誌
    'default': {
      'level': 'DEBUG',
      'class': 'logging.handlers.RotatingFileHandler', # 儲存到檔案
      'formatter': 'standard',
      'filename': logfile_path, # 日誌檔案
      'maxBytes': 1024*1024*5, # 日誌大小 5M
      'backupCount': 5,
      'encoding': 'utf-8', # 日誌檔案的編碼,再也不用擔心中文log亂碼了
     },
  },
  'loggers': {
    #logging.getLogger(__name__)拿到的logger配置
    #aa是生成器的名稱可以隨便寫
    'aa': {
      'handlers': ['default', 'console'], # 這裡把上面定義的兩個handler都加上,即log資料既寫入檔案又列印到螢幕
      'level': 'DEBUG',
      'propagate': True, # 向上(更高level的logger)傳遞,日誌的繼承
    },
  },
}


#通過一個字典來配置logging模組
logging.config.dictConfig(loggin_config.LOGGING_DIC)

#通過名稱來獲取一個生成器
aaloger=logging.getLogger('aa')

#輸出日誌
aaloger.info('測試資訊!')

#當要獲取的名稱不存在時,會返回一個預設的生成器
aaloger=logging.getLogger('aaa')
#輸出日誌
aaloger.warning('測試資訊!')

 

#瞭解知識點
日誌的繼承
自己來定義四種核心角色
import logging
mylog=logging.getLogger('father')
mylog.setLevel(10)

handler=logging.FileHandler('father.log',mode='a',encoding='utf-8')
mylog.addHandler(handler)

fmter=logging.Formatter(fmt='%(funcName)s %(module)s %(filename)s\
%(threadName)s %(levelname)s %(asctime)s %(message)s')
handler.setFormatter(fmter)

mylog.info('這是一條日誌資訊!')

#再獲取一個生成器,同時指定該生成器的父親是father這個生成器
sonlog=logging.getLogger('father.son')
sonlog.info('這是son輸出的日誌資訊!')
#繼承後子生成器可以直接使用父生成器的配置

#需求:子生成器的輸出位置與父生成器不同,格式相同
sonlog=logging.getLogger('father.son')
sonhandler=logging.FileHandler('son.txt',mode='a',encoding='utf-8')
sonlog.addHandler(sonhandler)
sonhandler.setFormatter(fmter)
sonlog.info('這是son輸出的日誌資訊!')
#子生成器在生成一個日誌時會自動給父生成器也發一個

#取消傳遞效果
sonlog.propagate=False