1. 程式人生 > >[ Python ] 模塊詳解

[ Python ] 模塊詳解

個數 反序列化 license 方式 windows 就是 hellip ket with

1. time 模塊

Functions:

time() -- return current time in seconds since the Epoch as a float
	返回當前時間,以秒為單位,從1870年開始就算,為浮點數
clock() -- return CPU time since process start as a float
	以浮點數計算的秒數返回當前 CPU 的時間
sleep() -- delay for a number of seconds given as a float
	表示線程掛起的時間
gmtime() -- convert seconds since Epoch to UTC tuple
	將一個時間戳轉換為 UTC 時間的 struct_time
localtime() -- convert seconds since Epoch to local time tuple
	格式化時間戳為本地時間 struct_time
asctime() -- convert time tuple to string
	接收時間元組並返回一個可讀形式的時間
ctime() -- convert time in seconds to string
	把時間戳轉換為 asctime() 的形式
mktime() -- convert local time tuple to seconds since Epoch
	接收 struct_time 對象作為參數,返回用秒數來表示時間的浮點數
strftime() -- convert time tuple to string according to format specification
	函數接收以時間元組,並返回可讀字符串表示當地時間,格式由參數format決定
strptime() -- parse string to time tuple according to format specification
	函數根據指定的格式把一個時間字符串解析為時間元組
tzset() -- change the local timezone
	根據環境變量TZ重新初始化時間相關設置

技術分享圖片

三種時間類型之間的轉換:

time_stamp: 時間戳,表現形式: 1531433179.1281905 秒作為單位的浮點數
struct_time:  結構化時間,表示形式:time.struct_time(tm_year=2018, tm_mon=7, tm_mday=13, tm_hour=6, tm_min=6, tm_sec=19, tm_wday=4, tm_yday=194, tm_isdst=0)
format_string: 格式化時間,表示形式:2018-07-13 06:11:02

時間轉換的詳細示意圖:

技術分享圖片

除了上面時間轉換的相關方法,還有幾個需要註意的方法:

技術分享圖片

(1)time.asctime
打印 ‘%a %b %d %H:%M:%S %Y‘ 可讀的時間格式

>>> print(time.asctime())
Fri Jul 13 06:31:32 2018

(2)time.ctime
將時間戳轉換格式為 ‘%a %b %d %H:%M:%S %Y‘ 可讀時間

>>> time.ctime(time.time())
‘Fri Jul 13 06:33:56 2018‘

(3)time.sleep
進程掛起的時間,參數單位為秒

>>> time.sleep(2)

2. random 模塊

用於生成隨機數的模塊

常用方法:

(1)random.random
隨機生成 0-1 之間的隨機數

>>> random.random()
0.34573032308214957

(2)random.randint
傳入參數必須是整數,隨機選取參數範圍內的整數,首尾都可以取

>>> random.randint(0, 100)
30

(3)random.randrange
傳入參數必須是整數,隨機選取參數範圍內的整數,首取尾不取
只會在1,2之間隨機

>>> random.randrange(1, 3)
1

(4)random.sample
參數的第一個參數是可叠代對象,第二個參數是隨機獲取元素的個數,返回列表類型

>>> random.sample((1, ‘23‘, [4,5]), 2)
[[4, 5], 1]
>>> str1 = random.sample((1, ‘23‘, [4,5]), 2)
>>> type(str1)
<class ‘list‘>

(5)random.choice
參數為可叠代對象,隨機返回其中的一個元素

>>> random.choice([‘a‘, ‘b‘, ‘c‘, ‘xyz‘])
‘xyz‘

(6)random.uniform
取任意整數範圍的浮點數

>>> random.uniform(1, 10)
8.77739630139806

(7)random.shuffle
打印列表或元組的順序,如洗牌

>>> item = [2,4,6,8,10]
>>> random.shuffle(item)
>>> item
[2, 8, 10, 6, 4]

實例:隨機驗證碼

import random

def v_code():
        ‘‘‘隨機生成 4 位的驗證碼‘‘‘
        ran_code = ‘‘
        for i in range(4):
                ran_int = random.randint(0, 9)  # 隨機獲取 0-9 之間任意一個整數
                ran_alf = chr(random.randint(65, 90))   # 隨機獲取 65-90之間一個隨機數,通過 chr 返回整數對應的 ASCII字符
                s = str(random.choice([ran_int, ran_alf]))  # 通過隨機 choice 選取其中一個
                ran_code += s   # 疊加字符串

3. OS模塊

  OS模塊是與操作系統交互的一個接口

常用方法:

(1)os.getcwd()
獲取當前工作目錄

>>> os.getcwd()
‘C:\\Users\\hkey‘

(2)os.chdir()
改變當前腳本工作目錄,相當於 shell ‘cd ‘命令

>>> os.chdir(‘..‘)
>>> os.getcwd()
‘C:\\Users‘

(3)os.curdir
返回當前目錄

>>> os.curdir
‘.‘

(4)os.pardir
返回當前目錄的父目錄字符串名

>>> os.pardir
‘..‘

(5)os.makedirs(‘dirname1/dirname2‘)
可生成多層遞歸目錄

>>> os.makedirs(‘abc/hkey‘)

(6)os.removedirs(‘dirname1‘)
若目錄為空,則刪除,並遞歸到上一級目錄,如若也為空,則刪除,以此類推

>>> os.removedirs(‘abc\hkey‘)
# 如果 hkey 目錄為空則刪除,如 abc 目錄也空則刪除

(7)os.mkdir(‘dirname‘)
生成單級目錄;相當於shell中 mkdir dirname

>>> os.mkdir(‘hkey‘)

(8)os.rmdir(‘filename‘)
刪除單級空目錄,若目錄不為空則無法刪除。

>>> os.rmdir(‘hkey‘)

(9)os.listdir(‘dirname‘)
列出指定目錄下的所有文件和子目錄,包括隱藏文件,並以列表方式打印

>>> os.listdir(r‘c:/python35‘)
[‘DLLs‘, ‘Doc‘, ‘include‘, ‘Lib‘, ‘libs‘, ‘LICENSE.txt‘, ‘NEWS.txt‘, ‘python.exe‘, ‘python3.dll‘, ‘python35.dll‘, ‘pythonw.exe‘, ‘README.txt‘, ‘Scripts‘, ‘tcl‘, ‘Tools‘, ‘vcruntime140.dll‘]

(10)os.remove()
刪除一個文件

>>> os.remove(‘abc.txt‘)

(11)os.rename(‘oldname‘, ‘newname‘)
重命名文件、目錄

>>> os.rename(‘abc.txt‘, ‘hkey.txt‘)

(12)os.stat(‘path/filename‘)
獲取文件/目錄信息

>>> os.stat(‘hkey.txt‘)
os.stat_result(st_mode=33206, st_ino=562949953433293, st_dev=2283361558, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1531447766, st_mtime=1531447766, st_ctime=1531447766)

(13)os.sep
輸出操作系統特定的路徑分隔符,win下為 ‘\\‘, Linux下為 ‘/‘

>>> os.sep
‘\\‘

(14)os.linesep
輸出當前平臺使用的行終止符, win 下為 ‘\r\n‘ Linux下為‘\n‘

>>> os.linesep
‘\r\n‘

(15)os.pathsep
輸出環境變量 ‘path‘ 用於分割文件路徑的字符串 win下為 ; Linux下為 :

>>> os.pathsep
‘;‘

(16)os.name
輸出字符串指定當前使用平臺, win --> ‘nt‘ , Linux --> ‘posix‘

>>> os.name
‘nt‘

(17)os.system(‘bash command‘)
輸入shell命令,直接顯示不能保存變量

>>> os.system(‘dir C:\\‘)
  驅動器 C 中的卷沒有標簽。
  卷的序列號是 9483-7444

  C:\ 的目錄

2018/07/09  11:16    <DIR>          AMD
2018/07/09  11:23    <DIR>          DRIVERS
2018/07/09  11:15    <DIR>          Intel
2018/07/09  19:08    <DIR>          PerfLogs
2018/07/09  15:04    <DIR>          Program Files
2018/07/09  15:50    <DIR>          Program Files (x86)
2018/07/09  14:47    <DIR>          Python35
2018/07/09  14:12    <DIR>          Users
2018/07/11  11:19    <DIR>          Windows
                              0 個文件              0 字節
                              9 個目錄 68,863,184,896

(18)os.environ
獲取系統環境變量

>>> os.environ
environ({‘LOCALAPPDATA‘: ‘C:\\Users\\hkey\\AppData\\Local‘......})

(19)os.path.abspath(path)
返回 path 絕對路徑

>>> os.path.abspath(‘etc‘)
‘C:\\Program Files\\Git\\etc‘

(20)os.path.split(path)
將 path 分割為 目錄 和 文件 2元素 元組

>>> os.path.split(r‘C:\Program Files\Git\etc\host‘)
(‘C:\\Program Files\\Git\\etc‘, ‘host‘)

(21)os.path.dirname(path)
返回path的目錄。其實就是 os.path.split(path)的第一個元素

>>> os.path.dirname(‘C:\Program Files\Git\etc‘)
‘C:\\Program Files\\Git‘

(22)os.path.basename(path)
返回 path 最後的文件名。如何 path 以 / 或 \\ 結尾,那麽就會返回空值。即 os.path.split(path) 的第二個元素

>>> os.path.basename(‘C:\Program Files\Git\etc\\‘)
‘‘
>>> os.path.basename(‘C:\Program Files\Git\etc/‘)
‘‘
>>> os.path.basename(‘C:\Program Files\Git\etc‘)
‘etc‘

(23)os.path.exists(path)
如果 path 存在, 返回 True;如果 path 不存在, 返回 False

>>> os.path.exists(‘C:\Program Files\Git\etc‘)
True
>>> os.path.exists(‘C:\Program Files\Git\etcc‘)
False

(24)os.path.isabs(path)
如果 path 是絕對路徑,返回 True

>>> os.path.isabs(‘etc‘)
False
>>> os.path.isabs(‘C:\Program Files\Git\etc‘)
True

(25)os.path.isfile(path)
如果 path 是一個存在的文件,返回 True、否則返回 False

>>> os.path.isfile(‘C:\Program Files\Git\etc‘)
False
>>> os.path.isfile(‘C:\Program Files\Git\etc\hosts‘)
True

(26)os.path.isdir(path)
如果 path 是一個存在的目錄,則返回 True,否則返回 False

>>> os.path.isdir(‘C:\Program Files\Git\etc‘)
True
>>> os.path.isdir(‘C:\Program Files\Git\etc\hosts‘)
False

(27)os.path.join(path1[, path2[, …]])
將多個路徑組合後返回,第一個絕對路徑之前的參數將被忽略

>>> os.path.join(‘\tmp\abc‘, ‘C:\Program Files\Git\etc‘, r‘conf\vhost‘)
‘C:\\Program Files\\Git\\etc\\conf\\vhost‘

(28)os.path.getatime(path)
返回 path 所指向的文件或者目錄的最後存取時間

>>> os.path.getatime(‘C:\Program Files\Git\etc‘)
1531118531.7878392
>>> os.path.getatime(‘C:\Program Files\Git\etc\hosts‘)
1468669537.155324

(29)os.path.getmtime(path)
返回 path 所指向的文件或者目錄的最後修改時間

>>> os.path.getmtime(‘C:\Program Files\Git\etc‘)
1531118531.7878392
>>> os.path.getmtime(‘C:\Program Files\Git\etc\hosts‘)
1468669537.155324

4. sys模塊

(1) sys.argv
命令行參數 List, 第一個元素是程序本身路徑

>python sys_test.py hello world
[‘sys_test.py‘, ‘hello‘, ‘world‘]

(2)sys.version
獲取 python 解釋程序的版本信息

>>sys.version
‘3.5.3 (v3.5.3:1880cb95a742, Jan 16 2017, 16:02:32) [MSC v.1900 64 bit (AMD64)]‘

(3)sys.path
返回模塊的搜索路徑,初始化時使用 python path 環境變量的值

sys.path
[‘D:\\Program Files (x86)\\JetBrains\\PyCharm 2017.3.3\\helpers\\pydev ......]

(4)sys.platform
返回操作系統平臺名稱

>>> sys.platform
‘win32‘

實例:進度條程序

import sys, time

for i in range(100):
        sys.stdout.write(‘#‘)
        sys.stdout.flush()
        time.sleep(0.2)

5. json & pickle

什麽是序列化:
我們把對象(變量)從內存中變成可存儲或傳輸的過程稱之為序列化,在 python 中叫 picking
序列化之後,就可以把虛擬化後的內容寫入磁盤,或者通過網絡傳輸到別的機器上;
反過來,把變量內容從序列化的對象重新讀到內存裏稱之為反序列化,即 unpicking

json
如果我們要在不同的編程語言之間傳遞對象,就必須把對象序列化為標準格式,比如 xml, 但更好的方法是虛擬化為 JSON,因為JSON表示出來就是一個字符串,
可以被所有語言讀取,也可以方便的存儲到磁盤或者通過網絡傳輸。JSON不僅是標準格式,並且比xml更快,而且可以直接在web頁面中讀取,非常方便。

JSON表示的對象就是標準的Javascript語言對象,JSON和Python內置的數據類型對應如下:

技術分享圖片

常用方法:
(1)json.dumps 序列化

(2)json.loads 反序列化

import json

# 序列化 -------------------------------
dic = {‘name‘: ‘hkey‘, ‘age‘: 22}

j = json.dumps(dic)
print(j, type(j))

# 執行結果:
# {"age": 22, "name": "hkey"} <class ‘str‘>

# 反序列化 --------------------------------

i = json.loads(j)
print(i, type(i))

# 執行結果:
# {‘age‘: 22, ‘name‘: ‘hkey‘} <class ‘dict‘>

(3)json.dump
序列化後寫入文件

(4)json.load
讀取文件中json格式數據後,反序列化

import json
dic = {‘name‘: ‘hkey‘, ‘age‘: 22}

# ----------- 序列化 -----------
with open(‘json.txt‘, ‘w‘, encoding=‘utf-8‘) as f:
        # 序列化後,直接存儲 json.txt 文件
        json.dump(dic, f)

# ----------- 反序列化 -----------

with open(‘json.txt‘, ‘r‘) as f:
        # 讀取文件中json類型數據並做反序列化
        data = json.load(f)
print(data, type(data))

# 執行結果:
# {‘age‘:22,‘name‘:‘hkey‘} <class‘dict‘>

pickle 模塊

作為 python 特有的類型和 python 的數據類型間進行轉換

(1)pickle.dumps
以字節對象形式返回封裝的對象,不需要寫入文件中;
(2)pickle.loads
從字節對象中讀取被封裝的對象,並返回;

import pickle
dic = {‘name‘: ‘hkey‘, ‘age‘: 22}

#------------序列化------------
j = pickle.dumps(dic)
print(j)

# 執行結果:
# b‘\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x16X\x04\x00\x00\x00nameq\x02X\x04\x00\x00\x00hkeyq\x03u.‘

#------------反序列化------------
data = pickle.loads(j)
print(data, type(data))

# 執行結果:
# {‘name‘: ‘hkey‘, ‘age‘: 22} <class ‘dict‘>

(3)pickle.dump
必填參數 file 表示 obj 要寫入的文件對象,file必須以二進制可寫模式打開,即 ‘wb‘
(4)pickle.load
必填參數 file 必須以二進制可讀模式打開,即 ‘rb‘, 其他都可選參數

import pickle
dic = {‘name‘: ‘hkey‘, ‘age‘: 22}
#------------序列化------------
with open(‘pickel.txt‘, ‘wb‘) as f:
        # 序列化後,以字節格式存入 pickel.txt 文件
        pickle.dump(dic, f)
#------------反序列化------------
with open(‘pickel.txt‘, ‘rb‘) as f:
        # 讀取文件中字節,並做反序列化
        data = pickle.load(f)

print(data)

# 執行結果:
#{‘name‘:‘hkey‘,‘age‘:22}

6. shelve 模塊

shelve 是一組簡單的數據存儲方案,他只有一個函數就是 open(), 這個函數接收一個參數就是文件名,並且文件名必須是 .dat類型的。
然後返回一個對象,可以把這個對象當作一個字典,當你存儲完畢的時候,就調用 close 函數來關閉

寫入:

import shelve

f = shelve.open(‘shelve.txt‘)
f[‘key1‘] = {‘name‘: ‘xiaofei‘, ‘age‘: 20}
f.close()

執行完畢會生成如下三個文件:

技術分享圖片

讀取:

import shelve

with shelve.open(‘shelve.txt‘) as f:
        name = f[‘key1‘][‘name‘]
print(name)

# 執行結果:
# xiaofei

7. configparser模塊

該模塊的作用就是使用模塊中的 ConfigParser(),創建一個對象使用對象的方法對指定的配置文件做 增刪改查 操作

(1 ) 寫入

import configparser

config = configparser.ConfigParser()
config[‘DEFAULT‘] = {‘ServerAliveInterval‘: ‘45‘,
                                            ‘Compression‘: ‘yes‘,
                                          ‘CompressionLevel‘: ‘9‘}

config[‘bitbucket.org‘] = {}
config[‘bitbucket.org‘][‘User‘] = ‘hg‘
config[‘topsecret.server.com‘] = {}
topsecret = config[‘topsecret.server.com‘]
topsecret[‘Host Port‘] = ‘50022‘
topsecret[‘ForwardX11‘] = ‘no‘
config[‘DEFAULT‘][‘ForwardX11‘] = ‘yes‘

with open(‘exmaple.ini‘, ‘w‘) as configfile:
        config.write(configfile)

(2)讀取

import configparser
config = configparser.ConfigParser()
config.read(‘example.ini‘)
print(config.sections())    # [‘bitbucket.org‘, ‘topsecret.server.com‘]
print(‘bytebong.com‘ in config)     # False
print(config[‘bitbucket.org‘][‘User‘])  # hg
print(config[‘DEFAULT‘][‘Compression‘])     # yes
print(config[‘topsecret.server.com‘][‘ForwardX11‘])     # no

for key in config[‘bitbucket.org‘]:
        print(key)

# user
# serveraliveinterval
# compression
# compressionlevel
# forwardx11

(3)增加

import configparser

config = configparser.ConfigParser()
config.read(‘example.ini‘)
config.add_section(‘xiaofei‘)
config[‘xiaofei‘] = {
        ‘name‘: ‘xiaofei‘,
        ‘age‘: 20
}

config.write(open(‘example.ini‘, ‘w‘))

(4)修改、刪除

import configparser

config = configparser.ConfigParser()
config.read(‘example.ini‘)
config.remove_section(‘bitbucket.org‘)      # 刪除 [bitbucket.org] 下所有內容
config.remove_option(‘xiaofei‘, ‘name‘)     # 刪除 [xiaofei] 下 name項
config.set(‘xiaofei‘, ‘age‘, ‘18‘)          # 修改 [xiaofei] age = 18 必須為str類型
config.write(open(‘i.ini‘, ‘w‘))            # 保存修改內容

8. hashlib模塊

  用於加密相關操作。主要用 md5 進行加密

import hashlib

m = hashlib.md5()
m.update(‘hello‘.encode(‘utf-8‘))
print(m.hexdigest())    # 5d41402abc4b2a76b9719d911017c592
m.update(‘world‘.encode(‘utf-8‘))
print(m.hexdigest())    # fc5e038d38a57032085441e7fe7010b0

m2 = hashlib.md5()
m2.update(‘helloworld‘.encode(‘utf-8‘))
print(m2.hexdigest())   # fc5e038d38a57032085441e7fe7010b0

以上加密存在缺陷,可以通過撞庫來反解,所以有必要對加密算法中添加自定義 key 再來做加密

import hashlib

hash = hashlib.sha256(‘888‘.encode(‘utf-8‘))
hash.update(‘aliyun‘.encode(‘utf-8‘))
print(hash.hexdigest()) #da7ecd435e6e0930532c115e7fe48c38d0405aa79586b0275717a0ab0a85acd1

9. logging模塊

  用於記錄日誌的模塊

import logging

logging.debug(‘debug message‘)
logging.info(‘info message‘)
logging.warning(‘warning message‘)
logging.error(‘error message‘)
logging.critical(‘critical message‘)

# 執行結果:
# WARNING:root:warning message
# ERROR:root:error message
# CRITICAL:root:critical message

默認情況下 python 的 logging 模塊將日誌打印到了標準輸出中,且只顯示了大於 WARING級別的日誌,這說明默認的日誌級別設置為 WARING
日誌級別等級排序(CRITICAL > ERROR > WARING > INFO > DEBUG > NOTSET)默認的日誌格式為日誌級別: Logger名稱:用戶輸出消息

(1)靈活配置日誌級別,日誌格式,輸出位置

import logging

logging.basicConfig(
        level=logging.DEBUG,
        format=‘%(asctime)s %(filename)s %(message)s‘,
        # filename=‘logg.txt‘,
        # filemode=‘w‘
)

logging.debug(‘debug message‘)
logging.info(‘info message‘)
logging.warning(‘warning message‘)
logging.error(‘error message‘)
logging.critical(‘critical message‘)

# 執行結果:
# 2018-07-14 08:51:56,441 logging_test.py debug message
# 2018-07-14 08:51:56,441 logging_test.py info message
# 2018-07-14 08:51:56,441 logging_test.py warning message
# 2018-07-14 08:51:56,441 logging_test.py error message
# 2018-07-14 08:51:56,441 logging_test.py critical message

可以在 logging.basicConfig() 函數中通過具體的參數來更改 logging 模塊默認行為,可用參數如下:

filename:用指定的文件名創建FiledHandler(後邊會具體講解handler的概念),這樣日誌會被存儲在指定的文件中。
filemode:文件打開方式,在指定了filename時使用這個參數,默認值為“a”還可指定為“w”。
format:指定handler使用的日誌顯示格式。 
datefmt:指定日期時間格式。 
level:設置rootlogger(後邊會講解具體概念)的日誌級別 
stream:用指定的stream創建StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者文件(f=open(‘test.log‘,‘w‘)),默認為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用戶輸出的消息

(2)logger 對象

import logging

logger = logging.getLogger()

fh = logging.FileHandler(‘test.log‘)

ch = logging.StreamHandler()

formatter = logging.Formatter(‘%(asctime)s - %(levelname)s - %(message)s‘)

fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh)
logger.addHandler(ch)

logger.debug(‘logger debug message‘)
logger.info(‘logger info message‘)
logger.warning(‘logger warning message‘)
logger.error(‘logger error message‘)
logger.critical(‘logger critical message‘)

# 執行結果:
# 2018-07-14 09:08:54,983 - WARNING - logger warning message
# 2018-07-14 09:08:54,983 - ERROR - logger error message
# 2018-07-14 09:08:54,983 - CRITICAL - logger critical message

代碼結構:

技術分享圖片

logging庫提供了多個組件:
Logger: 對象提供應用程序可直接使用的接口
Handler:發送日誌到適當的目的地
Filter: 提供了過濾日誌信息的方法
Formatter: 指定日誌顯示的格式

logger = logging.getLogger() 返回一個默認的 Logger 也是 root Logger,並應用默認的日誌級別、Handler 和 Formatter 設置
可以通過指定最低的日誌級別來顯示日誌信息:
Logger.DEBUG
Logger.INFO
Logger.WARING
Logger.ERROR
Logger.CRITICAL

# 執行結果:
# 2018-07-14 09:08:54,983 - WARNING - logger warning message
# 2018-07-14 09:08:54,983 - ERROR - logger error message
# 2018-07-14 09:08:54,983 - CRITICAL - logger critical message

從這個輸出可以看出 logger = logging.getLogger() 返回 Logger名為 root. 這裏沒有用 logger.setLevel(logging.Debug) 顯示的為 logger 設置日誌級別,所以使用默認的日誌級別
WARING,故結果只輸出了大於等於 WARING 級別的信息

如果創建兩個 logger 對象

技術分享圖片
import logging

logger = logging.getLogger()
# 創建一個handler,用於寫入日誌文件
fh = logging.FileHandler(test.log)

# 再創建一個handler,用於輸出到控制臺
ch = logging.StreamHandler()

formatter = logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(message)s)

fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh) #logger對象可以添加多個fh和ch對象
logger.addHandler(ch)

logger.debug(logger debug message)
logger.info(logger info message)
logger.warning(logger warning message)
logger.error(logger error message)
logger.critical(logger critical message)
    
##################################################
logger1 = logging.getLogger(mylogger)
logger1.setLevel(logging.DEBUG)

logger2 = logging.getLogger(mylogger)
logger2.setLevel(logging.INFO)

logger1.addHandler(fh)
logger1.addHandler(ch)

logger2.addHandler(fh)
logger2.addHandler(ch)

logger1.debug(logger1 debug message)
logger1.info(logger1 info message)
logger1.warning(logger1 warning message)
logger1.error(logger1 error message)
logger1.critical(logger1 critical message)

logger2.debug(logger2 debug message)
logger2.info(logger2 info message)
logger2.warning(logger2 warning message)
logger2.error(logger2 error message)
logger2.critical(logger2 critical message)
    
# 執行結果:
# 2018-07-14 09:30:39,054 - root - WARNING - logger warning message
# 2018-07-14 09:30:39,054 - root - ERROR - logger error message
# 2018-07-14 09:30:39,054 - root - CRITICAL - logger critical message
# 2018-07-14 09:30:39,054 - mylogger - INFO - logger1 info message
# 2018-07-14 09:30:39,054 - mylogger - INFO - logger1 info message
# 2018-07-14 09:30:39,055 - mylogger - WARNING - logger1 warning message
# 2018-07-14 09:30:39,055 - mylogger - WARNING - logger1 warning message
# 2018-07-14 09:30:39,055 - mylogger - ERROR - logger1 error message
# 2018-07-14 09:30:39,055 - mylogger - ERROR - logger1 error message
# 2018-07-14 09:30:39,055 - mylogger - CRITICAL - logger1 critical message
# 2018-07-14 09:30:39,055 - mylogger - CRITICAL - logger1 critical message
# 2018-07-14 09:30:39,055 - mylogger - INFO - logger2 info message
# 2018-07-14 09:30:39,055 - mylogger - INFO - logger2 info message
# 2018-07-14 09:30:39,055 - mylogger - WARNING - logger2 warning message
# 2018-07-14 09:30:39,055 - mylogger - WARNING - logger2 warning message
# 2018-07-14 09:30:39,055 - mylogger - ERROR - logger2 error message
# 2018-07-14 09:30:39,055 - mylogger - ERROR - logger2 error message
# 2018-07-14 09:30:39,055 - mylogger - CRITICAL - logger2 critical message
logger

這裏有兩個問題:
明明通過 logger1.setLevel(logging.DEBUG) 將 logger1的日誌級別設置為 DEBUG,為何顯示的時候沒有顯示出 DEBUG 級別的日誌信息?

因為 logger1 和 logger2 對應的是同一個 Logger 實例,只要 logging.getLogger( name ) 中名稱參數 name 相同則返回的 Logger實例就是同一個,且僅有一個
在 logger2實例中通過 logger2.setLevel(logging.INFO)設置mylogger的日誌級別為 logging.INFO,所以最後 logger1 的輸出遵從了後來設置的日誌級別。

為什麽 logger1、logger2 對應的每個輸出分別顯示兩次?
這是因為我們通過 logger=logging.getLogger() 顯示的創建了 root Logger , 而 logger1 = logging.getLogger(‘mylogger‘) 創建了 root logger的孩子,logger2同樣
那麽孩子就會將消息分發給他的 handler 進行處理也會傳遞給所有的祖先 Logger 處理

註釋掉 root 的 handler 處理:

技術分享圖片
import logging

logger = logging.getLogger()
# 創建一個handler,用於寫入日誌文件
fh = logging.FileHandler(test.log)

# 再創建一個handler,用於輸出到控制臺
ch = logging.StreamHandler()

formatter = logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(message)s)

fh.setFormatter(formatter)
ch.setFormatter(formatter)

# logger.addHandler(fh) #logger對象可以添加多個fh和ch對象
# logger.addHandler(ch)

logger.debug(logger debug message)
logger.info(logger info message)
logger.warning(logger warning message)
logger.error(logger error message)
logger.critical(logger critical message)

##################################################
logger1 = logging.getLogger(mylogger)
logger1.setLevel(logging.DEBUG)

logger2 = logging.getLogger(mylogger)
logger2.setLevel(logging.INFO)

logger1.addHandler(fh)
logger1.addHandler(ch)

logger2.addHandler(fh)
logger2.addHandler(ch)
        
logger1.debug(logger1 debug message)
logger1.info(logger1 info message)
logger1.warning(logger1 warning message)
logger1.error(logger1 error message)
logger1.critical(logger1 critical message)

logger2.debug(logger2 debug message)
logger2.info(logger2 info message)
logger2.warning(logger2 warning message)
logger2.error(logger2 error message)
logger2.critical(logger2 critical message)

# 執行結果:
# logger warning message
# logger error message
# logger critical message
# 2018-07-14 09:41:03,604 - mylogger - INFO - logger1 info message
# 2018-07-14 09:41:03,604 - mylogger - WARNING - logger1 warning message
# 2018-07-14 09:41:03,604 - mylogger - ERROR - logger1 error message
# 2018-07-14 09:41:03,604 - mylogger - CRITICAL - logger1 critical message
# 2018-07-14 09:41:03,604 - mylogger - INFO - logger2 info message
# 2018-07-14 09:41:03,604 - mylogger - WARNING - logger2 warning message
# 2018-07-14 09:41:03,604 - mylogger - ERROR - logger2 error message
logger

10. re模塊

  請參考:

    -------------re模塊鏈接-------------

[ Python ] 模塊詳解