Python基礎之模塊

模塊(module)的概念

在計算機程序的開發過程當中,隨着程序代碼越寫越多,在一個文件裏代碼就會愈來愈長,愈來愈不容易維護。node

爲了編寫可維護的代碼,咱們把不少函數分組,分別放到不一樣的文件裏,這樣,每一個文件包含的代碼就相對較少,不少編程語言都採用這種組織代碼的方式。在Python中,一個.py文件就稱之爲一個模塊(Module)。python

使用模塊有什麼好處?web

最大的好處是大大提升了代碼的可維護性。算法

其次,編寫代碼沒必要從零開始。當一個模塊編寫完畢,就能夠被其餘地方引用。咱們在編寫程序的時候,也常常引用其餘模塊,包括Python內置的模塊和來自第三方的模塊。shell

因此,模塊一共三種:編程

  • python標準庫
  • 第三方模塊
  • 應用程序自定義模塊

另外,使用模塊還能夠避免函數名和變量名衝突。相同名字的函數和變量徹底能夠分別存在不一樣的模塊中,所以,咱們本身在編寫模塊時,沒必要考慮名字會與其餘模塊衝突。可是也要注意,儘可能不要與內置函數名字衝突json

模塊導入方法bash

# 方法1
import modulr  # 在當前目錄直接調用模塊

# 方法2
from module_test import cal  # 二層目錄調用模塊

# 方法3
from web1.web2.web3 import cal1   #多層目錄調用模塊

# 方法4
# 使用該方法調用後可直接使用該模塊中的函數,但有可能與調用模塊中 已定義好的函數名重用,故不推薦使用
from module_test.cal import *  # 調用該模塊中的函數,*表明調用全部
res = cal(3,4)       
print(res)

模塊路徑數據結構

#獲取路徑
import sys
for i in sys.path:
    print(i)

#輸出結果:
S:\Myproject
S:\Python 3.5.1\python35.zip
S:\Python 3.5.1\DLLs
S:\Python 3.5.1\lib                  #存放標準庫
S:\Python 3.5.1
S:\Python 3.5.1\lib\site-packages    #存放第三方庫,擴充庫
 
#添加路徑
import os
pre_path = os.path.abspath('../')  #當前路徑
import sys
sys.path.append(pre_path)   #添加環境變量,臨時生效
 環境變量:永久生效方法:個人電腦--->系統屬性--->環境變量--->Path路徑中添加,以";" 分割。

包(package)的概念

咱們先設想一下,若是不一樣的人編寫的模塊名相同怎麼辦?爲了不衝突,Python又引進了按目錄app

來組織模塊的方法,稱爲包(package)。

假設,以下圖,個人兩個time_file.py模塊名字重名了,可是這兩個模塊的功能都不相同,若是這兩個模塊都在同一級目錄中,那麼我在其餘地方要調用這個time_file.py模塊,那麼這個時候就會發生衝突,在這裏咱們就能夠經過包來組織模塊,避免衝突,

方法是:選擇一個頂層包名,引入包之後,只要頂層的包名不與別人衝突,那這個包裏面的模塊都不會與別人衝突了。

請注意:每一個包目錄下來都會有一個__init__.py的文件,這個文件必須是存在的,不然,Python就不把這個目錄當成普通目錄,而不是一個包,__init__.py能夠是空文件,也能夠有python代碼,__init__.py自己就是一個文件,它的模塊命就是對應的包名,它通常因爲作接口文件。

time模塊

時間的相關操做,三種表示方式:

時間戳         1970年1月1日00:00開始的秒數             time.time()

格式化的字符串     2016-12-15 10:40:30                         time.strftime("%Y-%m-%d %X")   時間現實格式可自定

結構化時間           元祖的形式                                  time.localtime()  time.struct_time元祖中有9個元素:(年,月,日,時,分,秒,一年中第幾周,一年中第幾天,夏令時)

 

import time
 
# 1 time() :返回當前時間的時間戳
time.time()  #1473525444.037215
 
#----------------------------------------------------------
 
# 2 localtime([secs])
# 將一個時間戳轉換爲當前時區的struct_time。secs參數未提供,則以當前時間爲準。
time.localtime() #time.struct_time(tm_year=2016, tm_mon=9, tm_mday=11, tm_hour=0,
# tm_min=38, tm_sec=39, tm_wday=6, tm_yday=255, tm_isdst=0)
time.localtime(1473525444.037215)
 
#----------------------------------------------------------
 
# 3 gmtime([secs]) 和localtime()方法相似,gmtime()方法是將一個時間戳轉換爲UTC時區(0時區)的struct_time。
 
#----------------------------------------------------------
 
# 4 mktime(t) : 將一個struct_time轉化爲時間戳。
print(time.mktime(time.localtime()))#1473525749.0
 
#----------------------------------------------------------
 
# 5 asctime([t]) : 把一個表示時間的元組或者struct_time表示爲這種形式:'Sun Jun 20 23:21:05 1993'。
# 若是沒有參數,將會將time.localtime()做爲參數傳入。
print(time.asctime())#Sun Sep 11 00:43:43 2016
 
#----------------------------------------------------------
 
# 6 ctime([secs]) : 把一個時間戳(按秒計算的浮點數)轉化爲time.asctime()的形式。若是參數未給或者爲
# None的時候,將會默認time.time()爲參數。它的做用至關於time.asctime(time.localtime(secs))。
print(time.ctime())  # Sun Sep 11 00:46:38 2016
 
print(time.ctime(time.time()))  # Sun Sep 11 00:46:38 2016
 
# 7 strftime(format[, t]) : 把一個表明時間的元組或者struct_time(如由time.localtime()和
# time.gmtime()返回)轉化爲格式化的時間字符串。若是t未指定,將傳入time.localtime()。若是元組中任何一個
# 元素越界,ValueError的錯誤將會被拋出。
print(time.strftime("%Y-%m-%d %X", time.localtime()))#2016-09-11 00:49:56
 
# 8 time.strptime(string[, format])
# 把一個格式化時間字符串轉化爲struct_time。實際上它和strftime()是逆操做。
print(time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X'))
 
#time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6,
#  tm_wday=3, tm_yday=125, tm_isdst=-1)
 
#在這個函數中,format默認爲:"%a %b %d %H:%M:%S %Y"。
 
 
# 9 sleep(secs)
# 線程推遲指定的時間運行,單位爲秒。
 
# 10 clock()
# 這個須要注意,在不一樣的系統上含義不一樣。在UNIX系統上,它返回的是「進程時間」,它是用秒錶示的浮點數(時間戳)。
# 而在WINDOWS中,第一次調用,返回的是進程運行的實際時間。而第二次以後的調用是自第一次調用之後到如今的運行
# 時間,即兩次時間差。

 

不一樣時間格式之間的轉換方式

 

print(time.strftime("%Y-%m-%d %X",time.localtime()))  #結構化轉格式化
print(time.asctime(time.localtime()))  #結構化轉格式化,不可自定義格式
print(time.strptime("2016-12-25 18:33:24","%Y-%m-%d %X"))  #格式化轉結構化
print(time.mktime(time.localtime()))    #結構化轉時間戳
print(time.gmtime(1421770825.256))     #時間戳轉結構化
print(time.ctime(1421770825.256))   #時間戳轉格式化,不可自定義格式

random模塊

import random
 
print(random.random())          #用於生成一個0到1的隨機符點數: 0 <= n < 1.0
print(random.randint(1,2))      #用於生成一個指定範圍內的整數
print(random.randrange(1,10))   #從指定範圍內,按指定基數遞增的集合中獲取一個隨機數
print(random.uniform(1,10))     #用於生成一個指定範圍內的隨機符點數
print(random.choice('nick'))    #從序列中獲取一個隨機元素
li = ['nick','jenny','car',]
random.shuffle(li)              #用於將一個列表中的元素打亂
print(li)
li_new = random.sample(li,2)    #從指定序列中隨機獲取指定長度的片段(從li中隨機獲取2個元素,做爲一個片段返回)
print(li_new)
import random

def v_code():

    code = ''
    for i in range(5):  #生成隨機6位長度驗證碼,經過這裏控制

        num=random.randint(0,9)
        alf=chr(random.randint(65,90))
        add=random.choice([num,alf])
        code += str(add)
    return code

print(v_code())

# LT7Q6 (隨機生成的5位驗證碼,每次運行都不同)
驗證碼

 os模塊

os模塊是與操做系統交互的一個接口

os.getcwd() 獲取當前工做目錄,即當前python腳本工做的目錄路徑
os.chdir("dirname")  改變當前腳本工做目錄;至關於shell下cd
os.curdir  返回當前目錄: ('.')
os.pardir  獲取當前目錄的父目錄字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多層遞歸目錄
os.removedirs('dirname1')    若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推
os.mkdir('dirname')    生成單級目錄;至關於shell中mkdir dirname
os.rmdir('dirname')    刪除單級空目錄,若目錄不爲空則沒法刪除,報錯;至關於shell中rmdir dirname
os.listdir('dirname')    列出指定目錄下的全部文件和子目錄,包括隱藏文件,並以列表方式打印
os.remove()  刪除一個文件
os.rename("oldname","newname")  重命名文件/目錄
os.stat('path/filename')  獲取文件/目錄信息
os.sep    輸出操做系統特定的路徑分隔符,win下爲"\\",Linux下爲"/"
os.linesep    輸出當前平臺使用的行終止符,win下爲"\t\n",Linux下爲"\n"
os.pathsep    輸出用於分割文件路徑的字符串 win下爲;,Linux下爲:
os.name    輸出字符串指示當前使用平臺。win->'nt'; Linux->'posix'
os.system("bash command")  運行shell命令,直接顯示
os.environ  獲取系統環境變量
os.path.abspath(path)  返回path規範化的絕對路徑
os.path.split(path)  將path分割成目錄和文件名二元組返回
os.path.dirname(path)  返回path的目錄。其實就是os.path.split(path)的第一個元素
os.path.basename(path)  返回path最後的文件名。如何path以/或\結尾,那麼就會返回空值。即os.path.split(path)的第二個元素
os.path.exists(path)  若是path存在,返回True;若是path不存在,返回False
os.path.isabs(path)  若是path是絕對路徑,返回True
os.path.isfile(path)  若是path是一個存在的文件,返回True。不然返回False
os.path.isdir(path)  若是path是一個存在的目錄,則返回True。不然返回False
os.path.join(path1[, path2[, ...]])  將多個路徑組合後返回,第一個絕對路徑以前的參數將被忽略
os.path.getatime(path)  返回path所指向的文件或者目錄的最後存取時間
os.path.getmtime(path)  返回path所指向的文件或者目錄的最後修改時間

sys模塊

 

sys.argv           命令行參數List,第一個元素是程序自己路徑
sys.exit(n)        退出程序,正常退出時exit(0)
sys.version        獲取Python解釋程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
sys.platform       返回操做系統平臺名稱
import sys,time
for i in range(50):
    sys.stdout.write("*")
    time.sleep(0.5)
    sys.stdout.flush() #強制刷新打印到屏幕
進度條

json & pickle 模塊

用於序列化的兩個模塊

  • json,用於字符串 和 python數據類型間進行轉換
  • pickle,用於python特有的類型 和 python的數據類型間進行轉換

Json模塊提供了四個功能:dumps、dump、loads、load

pickle模塊提供了四個功能:dumps、dump、loads、load

  dump()函數接受一個文件句柄和一個數據對象做爲參數,把數據對象以特定的格式保存 到給定的文件中。當咱們使用load()函數從文件中取出已保存的對象時,pickle知道如何恢復這些對象到它們原本的格式。

  dumps()函數執行和dump() 函數相同的序列化。取代接受流對象並將序列化後的數據保存到磁盤文件,這個函數簡單的返回序列化的數據。

  loads()函數執行和load() 函數同樣的反序列化。取代接受一個流對象並去文件讀取序列化後的數據,它接受包含序列化後的數據的str對象, 直接返回的對象。

 

示例:

ps1: 把一個字典,寫入到文件中

1 dic = '{"name": "alex"}'
2 f = open("hello", "w")
3 f.write(dic)

執行結果:

會生成一個hello文件

1 {"name": "alex"}

 

ps2: 讀取文件方法,把字典轉成字符串

1 f_read=open("hello","r")  #讀取文件
2 data=f_read.read()
3 print(type(data))
4 data=eval(data)      #字典轉成字符串(eval的使用方法)
5 print(data["name"])

執行結果:

1 <class 'str'>
2 alex

json模塊方法:

ps1: 把字典轉換成json形式的字符串寫入文件中 (兩種方法效果同樣,只是寫法不一樣而已)

方法一:推薦用這種方法

#一、把字典轉換成json形式的字符串寫入文件中
import json
dic = {'name': 'alex'}
dic = json.dumps(dic)
f = open("hello", "w")
f.write(dic)

方法二:

1 import json
2 dic = {'name': 'alex'}
3 f = open("hello", "w")
4 dic = json.dump(dic, f)

執行結果:

會生成一個hello的文件,並寫入內容:

1 {"name": "alex"}

 

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

ps2:  把文件中json類型的字符串讀取出來轉換成字典

方法一:推薦用這種方法

#把文件中json類型的字符串讀取出來轉換成字典
import json
f = open('hello','r')
f = json.loads(f.read())
print(f)
print(type(f))

方法二:

1 import json
2 f = open('hello','r')
3 f = json.load(f)   #不經常使用這種方法
4 print(f)
5 print(type(f))

執行結果:

1 {'name': 'alex'} 
2 <class 'dict'>     #查看類型

 

注意點:

import json
#dct="{'1':111}"#json 不認單引號
#dct=str({"1":111})#報錯,由於生成的數據仍是單引號:{'one': 1}

dct='{"1":"111"}'
print(json.loads(dct))

#conclusion:
#        不管數據是怎樣建立的,只要知足json格式,就能夠json.loads出來,不必定非要dumps的數據才能loads

 

json的dumps,loads,dump,load功能總結:

json.dumps(x)    把python的(x)原對象轉換成json字符串的對象,主要用來寫入文件。

json.loads(f)       把json字符串(f)對象轉換成python原對象,主要用來讀取文件和json字符串

json.dump(x,f)  把python的(x)原對象,f是文件對象,寫入到f文件裏面,主要用來寫入文件的

json.load(file)  把json字符串的文件對象,轉換成python的原對象,只是讀文件

 

                                                                   pickle

##----------------------------序列化
import pickle
 
dic={'name':'alvin','age':23,'sex':'male'}
 
print(type(dic))#<class 'dict'>
 
j=pickle.dumps(dic)
print(type(j))#<class 'bytes'>
 
 
f=open('序列化對象_pickle','wb')#注意是w是寫入str,wb是寫入bytes,j是'bytes'
f.write(j)  #-------------------等價於pickle.dump(dic,f)
 
f.close()
#-------------------------反序列化
import pickle
f=open('序列化對象_pickle','rb')
 
data=pickle.loads(f.read())#  等價於data=pickle.load(f)
 
 
print(data['age'])    

  Pickle的問題和全部其餘編程語言特有的序列化問題同樣,就是它只能用於Python,而且可能不一樣版本的Python彼此都不兼容,所以,只能用Pickle保存那些不重要的數據,不能成功地反序列化也不要緊。

 

shelve 模塊

 shelve模塊比pickle模塊簡單,只有一個open函數,返回相似字典的對象,可讀可寫;key必須爲字符串,而值能夠是python所支持的數據類型

#添加鍵值對到文件中,會生成三個文件,並寫入字典內容

import shelve

f = shelve.open(r'shelve1')  # 目的:將一個字典放入文本 f={}
f['stu1_info']={'name':'alex','age':'18'}
f['stu2_info']={'name':'alvin','age':'20'}
f['school_info']={'website':'oldboyedu.com','city':'beijing'}
f.close()

執行結果:

會生成三個文件:shelvel.dat,shelve1.dir,shelve1.bak,其中shelvel.bak中內容以下:

1 'stu1_info', (0, 49)           #生成只有計算機能識別的語言
2 'stu2_info', (512, 50)
3 'school_info', (1024, 67)

 

取出age的值

import shelve

f = shelve.open(r'shelve1')
print(f.get('stu1_info')['age'])  #取出age的值
print(f.get('stu2_info')['age'])

結果>>>
1 18
2 20

 

xml 模塊

  xml是實現不一樣語言或程序之間進行數據交換的協議,跟json差很少,但json使用起來更簡單,不過,古時候,在json還沒誕生的黑暗年代,你們只能選擇用xml呀,至今不少傳統公司如金融行業的不少系統的接口還主要是xml。

xml的格式以下,就是經過<>節點來區別數據結構的:

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

xml協議在各個語言裏的都 是支持的,在python中能夠用如下模塊操做xml:

 
 

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
print(root.tag)
 
#遍歷xml文檔
for child in root:
    print(child.tag, child.attrib)
    for i in child:
        print(i.tag,i.text)
 
#只遍歷year 節點
for node in root.iter('year'):
    print(node.tag,node.text)

 
 

    #執行結果:
             year 2008
             year 2011
         year 2011
#---------------------------------------

 
 

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
 
#修改
for node in root.iter('year'):
    new_year = int(node.text) + 1  #2008+1=2009
    node.text = str(new_year)
    node.set("updated","yes")      #修改經過set,加個屬性yes
 
tree.write("xmltest.xml")
 
 #執行結果:
      會生成一個新的xmltest.xml文件,內容中會添加
      <year updated="yes">2009</year>  #年份+1,加個yes屬性
#刪除node
for country in root.findall('country'):   #經過對country進行遍歷
   rank = int(country.find('rank').text)  #再用find找到rank
   if rank > 50:                          #再判斷>50的值
     root.remove(country)                 #再用remove刪除
 
tree.write('output.xml')                  #寫到一個新文件中

 

本身建立xml文檔:

import xml.etree.ElementTree as ET    #as後面的ET是前面的類的別名,名稱隨便取
 
 
new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
 
et = ET.ElementTree(new_xml) #生成文檔對象  (記住重點)
et.write("test.xml", encoding="utf-8",xml_declaration=True)  (記住重點)
 
ET.dump(new_xml) #打印生成的格式

執行結果:

會生成一個test.xml的文件:

<?xml version='1.0' encoding='utf-8'?>

<namelist>
    <name enrolled="yes">
        <age checked="no" />
        <sex>33</sex>
    </name>
    <name enrolled="no">
        <age>19</age>
    </name>
</namelist>

 configparser 模塊

configparser 模塊做用: 用來讀寫配置文件。

 

1、常見文檔格式以下:
一、先新建一個名字爲confile文件,寫入下面內容:

[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
  
[bitbucket.org]
User = hg
  
[topsecret.server.com]
Port = 50022
ForwardX11 = no

 

ps1:寫入一個文件

import configparser

config = configparser.ConfigParser()     #config={}

config["DEFAULT"] = {'ServerAliveInterval': '45',
                     'Compression': 'yes',
                     'CompressionLevel': '9'}

with open('example1.ini', 'w') as f:
    config.write(f)

執行結果:

#會生成example1.ini文件,內容以下:
[DEFAULT]
compressionlevel = 9
compression = yes
serveraliveinterval = 45

 

ps2:生成多個鍵值對

import configparser

config = configparser.ConfigParser()     #config={}

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'      # mutates the parser
topsecret['ForwardX11'] = 'no'        # same here

with open('example1.ini', 'w') as f:
    config.write(f)

執行結果:

#會生成example1.ini文件,內容以下:

[DEFAULT]
compression = yes
compressionlevel = 9
serveraliveinterval = 45

[bitbucket.org]
user = hg

[topsecret.server.com]
host port = 50022
forwardx11 = no
import configparser

config = configparser.ConfigParser()

#---------------------------------------------查
print(config.sections())   #[]

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


print(config.options('bitbucket.org'))#['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
print(config.items('bitbucket.org'))  #[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')]

print(config.get('bitbucket.org','compression'))#yes


#---------------------------------------------刪,改,增(config.write(open('i.cfg', "w")))


config.add_section('yuan')

config.remove_section('topsecret.server.com')
config.remove_option('bitbucket.org','user')

config.set('bitbucket.org','k1','11111')

config.write(open('i.cfg', "w"))

增刪改查
增刪改查

hashlib 模塊

hashlib 明文變成密文,不能反解
用於加密相關的操做,3.x裏代替了md5模塊和sha模塊,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

md5算法 明文變成密文

 

ps1:md5算法

1 import hashlib
2 
3 obj=hashlib.md5()
4 obj.update("admin".encode("utf8"))
5 print(obj.hexdigest())

執行結果:

21232f297a57a5a743894a0e4a801fc3 (長度32位)

 

ps2:

import hashlib

#md5加密+字符串,生成密碼。就沒法破解
obj=hashlib.md5("sssdsdsb".encode("utf8"))   #在md5裏面加點字符串,再生成,就無法破解
obj.update("admin".encode("utf8"))

print(obj.hexdigest())

執行結果:

639cd764cf1bab2bebaa5804e37530e6

 

ps3:

以上加密算法雖然依然很是厲害,但時候存在缺陷,即:經過撞庫能夠反解。因此,有必要對加密算法中添加自定義key再來作加密。

####### 256 位########

1 import hashlib
2 
3 hash = hashlib.sha256('898oaFs09f'.encode('utf8'))
4 hash.update('alvin'.encode('utf8'))
5 print(hash.hexdigest()) 

執行結果:

e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7

 

ps4:

python 還有一個 hmac 模塊,它內部對咱們建立 key 和 內容 再進行處理而後再加密:

1 import hmac
2 
3 h = hmac.new('alvin'.encode('utf8'))
4 h.update('hello'.encode('utf8'))
5 print (h.hexdigest())

執行結果:

320df9832eab4c038b6c1d7ed73a5940

 

logging 模塊

一. logging模塊

ps1:

import logging  

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

執行結果:  (默認是WARNING級別,因此只顯示三條信息)

1 WARNING:root:warning message
2 ERROR:root:error message
3 CRITICAL:root:critical message 

日誌級別:通常info就夠用
默認狀況下Python的logging模塊將日誌打印到了標準輸出中,且只顯示了大於等於WARNING級別的日誌,這說明默認的日誌級別設置爲WARNING
日誌級別等級CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET(從高到低),默認的日誌格式爲日誌級別:Logger名稱:用戶輸出消息。

 

ps2:設置參數,調日誌級別。調整爲DEBUG級別,顯示5條信息

import logging

logging.basicConfig(
level=logging.DEBUG
)

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

執行結果:顯示5條信息

1 DEBUG:root:debug message
2 INFO:root:info message
3 WARNING:root:warning message
4 ERROR:root:error message
5 CRITICAL:root:critical message

 

ps3:設置filename把日誌寫入到文件中,並參過加w參數,控制他每次只寫5條,不重複的記錄

import logging

logging.basicConfig(
level=logging.DEBUG,           #默認信息顯示在屏幕上面
filename="logger.log",         #經過加filename參數,以追加的方式,把日誌信息寫入到文件中,每次重複運行都會往裏面寫5條記錄
filemode="w",                  #經過加w參數,就能夠控制他,每次只寫5條記錄。不會重複往裏寫相同記錄
)

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

執行結果:

會建立一個logger.log日誌,並寫入五條記錄
DEBUG:root:debug message
INFO:root:info message
WARNING:root:warning message
ERROR:root:error message
CRITICAL:root:critical message

 

ps4:給logging加上參數,顯示時間,行號等信息。

import logging

logging.basicConfig(
level=logging.DEBUG,     #默認信息顯示在屏幕上面
filename="logger.log",   #經過加filename參數,以追加的方式,把日誌信息寫入到文件中,每次重複運行都會往裏面寫5條記錄
filemode="w",            #經過加w參數,就能夠控制他,每次只寫5條記錄。不會重複往裏寫相同記錄
# format="%(asctime)s",  #加上時間
format="%(asctime)s %(filename)s[%(lineno)d]  %(message)s"  #asctime 時間,lineno 行號,message 信息,還能夠加其它信息參數
)

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

執行結果:

# 會建立一個logger.log日誌,並寫入五條記錄
2016-12-15 14:10:33,615 logging_s1.py[15]  debug message
2016-12-15 14:10:33,616 logging_s1.py[16]  info message
2016-12-15 14:10:33,616 logging_s1.py[17]  warning message
2016-12-15 14:10:33,616 logging_s1.py[18]  error message
2016-12-15 14:10:33,617 logging_s1.py[19]  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對象(自定義日誌格式,常常用的一種方法) 重點掌握

上述幾個例子中咱們瞭解到了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分別用以記錄不一樣級別的日誌信息),logging.basicConfig()(用默認日誌格式
(Formatter)爲日誌系統創建一個默認的流處理器(StreamHandler),設置基礎配置(如日誌級別等)並加到root logger(根Logger)中)這幾個logging模塊級別的函數,另外還有一個模塊級別的函數
是logging.getLogger([name])(返回一個logger對象,若是沒有指定名字將返回root logger)

 

原理圖:

ps1:

import logging

logger=logging.getLogger()         #建立一個大對象

fh=logging.FileHandler("test_log") #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容
ch=logging.StreamHandler()         #向屏幕上發送內容

fm=logging.Formatter("%(asctime)s  %(message)s")   #這個也是一個對象,做用是:定義日誌格式

fh.setFormatter(fm)     #往文件裏寫內容
ch.setFormatter(fm)     #往屏幕上輸出內容

logger.addHandler(fh)   #對象,相似於吸別人內力,把fh吃掉
logger.addHandler(ch)   #對象,相似於吸別人內力,把ch吃掉

logger.debug("debug")   #輸出日誌的級別
logger.info("info")
logger.warning("warning")
logger.error("error")
logger.critical("critical")

執行結果:

會生成一個test_log的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。
文件內容以下:
2016-12-15 14:38:27,657  warning
2016-12-15 14:38:27,658  error
2016-12-15 14:38:27,658  critical

屏幕輸出信息以下:
2016-12-15 14:38:27,657  warning
2016-12-15 14:38:27,658  error
2016-12-15 14:38:27,658  critical

 

ps2: logger.setLevel("DEBUG")   調整日誌級別,控制日誌顯示信息,DEBUG顯示5條記錄

import logging

logger=logging.getLogger()         #建立一個大對象

fh=logging.FileHandler("test_log") #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容
ch=logging.StreamHandler()         #向屏幕上發送內容

fm=logging.Formatter("%(asctime)s  %(message)s")   #這個也是一個對象,做用是:定義日誌格式

fh.setFormatter(fm)      #往文件裏寫內容
ch.setFormatter(fm)      #往屏幕上輸出內容

logger.addHandler(fh)    #對象,相似於吸別人內力,把fh吃掉
logger.addHandler(ch)    #對象,相似於吸別人內力,把ch吃掉
logger.setLevel("DEBUG") #設置日誌級別,控制日誌輸入多少條信息


#-------------從這裏開始都是在操做log----------------

logger.debug("debug")   #輸出日誌的級別
logger.info("info")
logger.warning("warning")
logger.error("error")
logger.critical("critical")

執行結果:

# 會生成一個test_log的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。
文件內容以下:
2016-12-15 14:54:37,036  debug
2016-12-15 14:54:37,037  info
2016-12-15 14:54:37,038  warning
2016-12-15 14:54:37,038  error
2016-12-15 14:54:37,039  critical

#屏幕輸出信息以下:
2016-12-15 14:54:37,036  debug
2016-12-15 14:54:37,037  info
2016-12-15 14:54:37,038  warning
2016-12-15 14:54:37,038  error
2016-12-15 14:54:37,039  critical

ps3:寫成函數的形式,並有返回值

import logging

def logger():

    logger=logging.getLogger()         #建立一個大對象

    fh=logging.FileHandler("test_log") #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容
    ch=logging.StreamHandler()         #向屏幕上發送內容

    fm=logging.Formatter("%(asctime)s  %(message)s")   #這個也是一個對象,做用是:定義日誌格式

    fh.setFormatter(fm)       #往文件裏寫內容
    ch.setFormatter(fm)       #往屏幕上輸出內容

    logger.addHandler(fh)     #對象,相似於吸別人內力,把fh吃掉
    logger.addHandler(ch)     #對象,相似於吸別人內力,把ch吃掉
    logger.setLevel("DEBUG")  #設置日誌級別,控制日誌輸入多少條信息

    return logger

#-------------從這裏開始都是在操做log----------------
logger=logger()         #這個日誌就作成了一個接口,想在其它地方使用,直接調用他就能夠啦!

logger.debug("debug")   #輸出日誌的級別
logger.info("info")
logger.warning("warning")
logger.error("error")
logger.critical("critical")

執行結果:

會生成一個test_log的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。
文件內容以下:
2016-12-15 14:54:37,036  debug
2016-12-15 14:54:37,037  info
2016-12-15 14:54:37,038  warning
2016-12-15 14:54:37,038  error
2016-12-15 14:54:37,039  critical

屏幕輸出信息以下:
2016-12-15 14:54:37,036  debug
2016-12-15 14:54:37,037  info
2016-12-15 14:54:37,038  warning
2016-12-15 14:54:37,038  error
2016-12-15 14:54:37,039  critical

 

ps4 : 只在屏幕文件中寫入日誌,不在屏幕上面顯示

import logging

def logger():

    logger=logging.getLogger()         #建立一個大對象

    fh=logging.FileHandler("test_log") #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容
    #ch=logging.StreamHandler()        #向屏幕上發送內容

    fm=logging.Formatter("%(asctime)s  %(message)s")   #這個也是一個對象,做用是:定義日誌格式

    fh.setFormatter(fm)      #往文件裏寫內容
    #ch.setFormatter(fm)     #往屏幕上輸出內容

    logger.addHandler(fh)    #對象,相似於吸別人內力,把fh吃掉
    #logger.addHandler(ch)   #對象,相似於吸別人內力,把ch吃掉
    logger.setLevel("DEBUG") #設置日誌級別,控制日誌輸入多少條信息

    return logger

#-------------從這裏開始都是在操做log----------------
logger=logger()         #這個日誌就作成了一個接口,在其它地方,直接調用他就能夠啦!

logger.debug("debug")   #輸出日誌的級別
logger.info("info")
logger.warning("warning")
logger.error("error")
logger.critical("critical")

執行結果:

#會生成一個test_log的文件,同時往裏面寫入信息,不會在屏幕上面顯示信息。
#文件內容以下:
2016-12-15 14:54:37,036  debug
2016-12-15 14:54:37,037  info
2016-12-15 14:54:37,038  warning
2016-12-15 14:54:37,038  error
2016-12-15 14:54:37,039  critical

 

ps5: 沒有根用戶

若是咱們再建立兩個logger對象

import logging

logger1 = logging.getLogger('mylogger')   #默認是根,這裏表明他是子用戶(兩個用戶是同級)
#logger1 = logging.getLogger('mylogger.sontree')   #若是mylogger下再建立一個字對象,就用.sontree;等於他就是mylogger的下級對象。
logger1.setLevel(logging.DEBUG)           #第一次是DEBUG級別

logger2 = logging.getLogger('mylogger')   #默認是根,這裏表明他是子用戶(兩個用戶是同級)
logger2.setLevel(logging.INFO)            #第二次是INFO級別,覆蓋第一次的級別,因此打印結果是INFO級別顯示

fh=logging.FileHandler("test_log-new")    #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容
ch=logging.StreamHandler()                #向屏幕上發送內容

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

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

執行結果:

logger1 and logger2各打印4條信息
生成一個test_log-new的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。
文件內容以下:
logger1 info message
logger1 warning message
logger1 error message
logger1 critical message
logger2 info message
logger2 warning message
logger2 error message
logger2 critical message

#屏幕上面顯示的內容
logger1 info message
logger1 warning message
logger1 error message
logger1 critical message
logger2 info message
logger2 warning message
logger2 error message
logger2 critical message

 

ps6: 添加根用戶  (lgger和mylogger是父子關係) (注意日誌輸出問題)

import logging

logger = logging.getLogger()              #根用戶(根用戶級別,沒有定義日誌級別,默認warning級別,因此是3條信息

logger1 = logging.getLogger('mylogger')   #默認是根,這裏表明他是子用戶(兩個用戶是同級)
logger1.setLevel(logging.DEBUG)           #第一次是DEBUG級別,默認是打印五條信息,可是他打印信息的時候,會先去找父,若是有父,他就會多打印一遍,因此輸出是10條信息

fh=logging.FileHandler("test_log-new")    #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容
ch=logging.StreamHandler()                #向屏幕上發送內容

logger.addHandler(ch)                     #添加一個根用戶
logger.addHandler(fh)

logger1.addHandler(fh)                    #添加一個子用戶
logger1.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')

#打印4條信息
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')

輸出結果:

生成一個test_log-new的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。
文件內容以下:
logger warning message
logger error message
logger critical message    #前三條是根輸出的三條信息
logger1 debug message      #後10條是子輸出的10條信息,爲何會輸入10條呢?
logger1 debug message      #第一次是DEBUG級別,默認是打印五條信息,可是他打印信息的時候,會先去找父,若是有父,他就會多打印一遍,因此輸出是5+5=10條信息
logger1 info message
logger1 info message
logger1 warning message
logger1 warning message
logger1 error message
logger1 error message
logger1 critical message
logger1 critical message

 #屏幕輸出內容以下:
logger warning message
logger error message
logger critical message    
logger1 debug message
logger1 debug message
logger1 info message
logger1 info message
logger1 warning message
logger1 warning message
logger1 error message
logger1 error message
logger1 critical message
logger1 critical message

 

ps7:添加根用戶  (控制根用戶不輸入,只輸出子用戶信息)

import logging

logger = logging.getLogger()                #根用戶(根用戶級別,沒有定義日誌級別,默認warning級別,因此是3條信息

logger1 = logging.getLogger('mylogger')     #默認是根,這裏表明他是子用戶(兩個用戶是同級)
logger1.setLevel(logging.DEBUG)             #第一次是DEBUG級別,默認是打印五條信息,可是他打印信息的時候,會先去找父,若是有父,他就會多打印一遍,因此輸出是10條信息

fh=logging.FileHandler("test_log-new")      #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容
ch=logging.StreamHandler()                  #向屏幕上發送內容

logger1.addHandler(fh)                      #添加一個子用戶
logger1.addHandler(ch)

#打印4條信息
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')

執行結果:

#生成一個test_log-new的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。
文件內容以下:
logger1 debug message
logger1 info message
logger1 warning message
logger1 error message
logger1 critical message

#屏幕輸出內容以下:
logger1 debug message
logger1 info message
logger1 warning message
logger1 error message
logger1 critical message
相關文章
相關標籤/搜索