1. 程式人生 > >Python基礎之(常用模組)

Python基礎之(常用模組)

一、時間模組(time、datetime)

Python中有三種時間的表示方式:

  • 時間戳               1970年1月1日之後的秒,即:time.time()
  • 格式化時間    2014-11-11 11:11,    即:time.strftime('%Y-%m-%d')
  • 結構化時間          元組包含了:年、日、星期等... time.struct_time    即:time.localtime()

1.1、幾種時間表示方式的轉換

#時間戳轉結構化時間
import time
y=time.time()  #時間戳
x=time.localtime(y) #時間戳轉換結構化時間
#結構化時間轉成時間戳
z=time.mktime(x)   #結構化時間z轉時間戳
time.gmtime()  #世界標準時間(結構化時間)


#結構化時間轉換為格式化時間
time.strftime(%Y-%m-%d-%b %H:%M:%S',x)) #可帶引數指定結構化時間
time.strftime('%Y/%m/%d %H:%M:%S')  #沒有引數預設就是localtime
#格式化時間轉換成結構化時間
time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X'))
#strptime(string, format)

#  %Y  %m %d %H %M %S    %X          %a %b
#  年   月 日 時 分  秒  時分秒統稱     周  月


time.asctime() 
#把一個表示時間的元組或者struct_time表示為這種形式:'Sun Jun 20 15:21:05 1998',如果沒有引數,將會將time.localtime()作為引數傳入
time.ctime()
#把一個時間戳(按秒計算的浮點數)轉化為time.asctime()的形式。如果引數未給或者為None的時候,將會預設time.time()為引數

1.2、datetime模組

import datetime
  
print(datetime.datetime.now())   #返回格式 2018-12-16 17:12:41.621179
print(datetime.date.fromtimestamp(time.time()) )# 時間戳直接轉成日期格式 2018-12-16
print(datetime.datetime.now() + datetime.timedelta(3)) #當前時間+3天
print(datetime.datetime.now() + datetime.timedelta(-3)) #當前時間-3天
print(datetime.datetime.now() + datetime.timedelta(hours=3)) #當前時間+3小時
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #當前時間+30分
print(datetime.datetime.now() + datetime.timedelta(seconds=30)) #當前時間+30秒


n_time  = datetime.datetime.now()
print(n_time.replace(minute=3,hour=2)) #時間替換

執行結果:

 二、random 隨機模組

import random   #隨機模組
random.random()   #0-1 浮點型
random.uniform(1,3)  # 隨機取1-3的浮點數
random.randint(1,4) #隨機取1-4的整型
random.randrange(1,4)  #隨機取1-3的整數
random.choice([1,23,[22]])  #列表隨機取一個值
print(random.sample([1,2,3],3))  #列表隨機取多個值

list=[1,3,5,7,9]
random.shuffle(list)  #隨機打亂列表順序
print(list)
chr(random.randint(65,90))  #隨機大寫字母A-Z
chr(random.randint(97,122))  #隨機小寫字母a-z

 隨機取4個值要求包含0-9,a-z,A-Z

import random
def code():
    li = []
    for i in range(1,5):
        a=random.randint(0,9)
        b=chr(random.randint(65,90))
        c=chr(random.randint(97,122))
        c=random.sample([a,b,c],1)
        li.append(c)
    return li
print(code())

 其實上面這個例子並不嚴謹,0-9,a-z,A-Z各取一個,然後在從三個裡面再任意取一個,把獲取的四個值任意排序即可

 

三、OS模組

#當前工作目錄相關的
os.getcwd() #獲取當前工作目錄,即當前python指令碼工作的目錄路徑
os.chdir("dirname")  #改變當前指令碼工作目錄;相當於shell下cd
os.curdir  #返回當前目錄: ('.')
os.pardir  #獲取當前目錄的父目錄字串名:('..')

#和檔案相關
os.makedirs('name1/name2')    #可生成多層遞迴目錄
os.removedirs('dirname')    #刪除多層目錄,為空刪除,否則報錯
os.mkdir('dirname')    #生成單級目錄;相當於shell中mkdir dirname
os.rmdir('dirname')    #刪除單級空目錄,若目錄不為空則無法刪除
os.listdir('dirname')    #列出指定目錄下的所有檔案和子目錄,包括隱藏檔案
os.remove('filename')   #刪除一個檔案
os.rename("oldname","newname")   #重新命名檔案/目錄
os.stat('path/filename')    #獲取檔案/目錄資訊

# 和執行系統命令相關
os.system("bash command")  #執行系統命令,直接顯示
os.popen("bash command").read()  #執行系統命令,獲取執行結果
os.environ  #獲取系統環境變數
os.name()  #字串指示當前使用平臺。win->'nt'; Linux->'posix'

#path系列,和路徑相關
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(path,*paths)  #將多個路徑組合後返回
os.path.getatime(path)  #返回path所指向的檔案或者目錄的最後訪問時間
os.path.getmtime(path)  #返回path所指向的檔案或者目錄的最後修改時間
os.path.getsize(path) #返回path的大小

os.stat('path/filename')  獲取檔案/目錄資訊 的詳細說明

st_mode: inode 保護模式
st_ino: inode 節點號。
st_dev: inode 駐留的裝置。
st_nlink: inode 的連結數。
st_uid: 所有者的使用者ID。
st_gid: 所有者的組ID。
st_size: 普通檔案以位元組為單位的大小;包含等待某些特殊檔案的資料。
st_atime: 上次訪問的時間。
st_mtime: 最後一次修改的時間。
st_ctime: 由作業系統報告的"ctime"。在某些系統上(如Unix)是最新的元資料更改的時間,在其它系統上(如Windows)是建立時間

OS模組中os.path.join()\basename()\split() 比較重要(對檔案路徑拼接、檔名操作等)

四、sys模組
sys.argv          # 命令列引數,第一個元素是程式本身路徑,後面為輸入引數(list)
sys.exit()        #退出程式,正常退出時exit(0)
sys.version        #獲取Python解釋程式的版本資訊
sys.maxint         #最大的Int值
sys.path           #返回模組的搜尋路徑,初始化時使用PYTHONPATH環境變數的值
sys.platform      # 返回作業系統平臺名稱
sys.stdin          #輸入相關
sys.stdout         #輸出相關
sys.stderror       #錯誤相關
sys.stdout.write("#")  #輸出"#"
sys.stdout.flush() #重新整理快取

 

五、資料轉換相關(序列化)

5.1、josn 用於【字串】和 【python基本資料型別】 間進行轉換

  josn模組提供了四個功能:dumps、dump、loads、load

#dumps和loads
import json
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = json.dumps(dic)  #序列化:將一個字典轉換成一個字串
print(type(str_dic),str_dic)  #<class 'str'> {"k3": "v3", "k1": "v1", "k2": "v2"}
#注意,json轉換完的字串型別的字典中的字串是由""表示的

dic2 = json.loads(str_dic)  #反序列化:將一個字串格式的字典轉換成一個字典
#注意,要用json的loads功能處理的字串型別的字典中的字串必須由""表示
print(type(dic2),dic2)  #<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}


list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}]
str_dic = json.dumps(list_dic) #也可以處理巢狀的資料型別 
print(type(str_dic),str_dic) #<class 'str'> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]
list_dic2 = json.loads(str_dic)
print(type(list_dic2),list_dic2) #<class 'list'> [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}]
#dump和load
import json
f = open('json_file','w')
dic = {'k1':'v1','k2':'v2','k3':'v3'}
json.dump(dic,f)  #dump方法接收一個檔案控制代碼,直接將字典轉換成json字串寫入檔案
f.close()

f = open('json_file')
dic2 = json.load(f)  #load方法接收一個檔案控制代碼,直接將檔案中的json字串轉換成資料結構返回
f.close()
print(type(dic2),dic2)

5.2、pickle 用於【python特有的型別】 和 【python基本資料型別】間進行轉換

pickle模組提供了四個功能:dumps、loads、dump、load  (不僅可以序列化字典,列表...可以把python中任意的資料型別序列化

import pickle
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = pickle.dumps(dic)
print(str_dic)  #一串二進位制內容

dic2 = pickle.loads(str_dic)
print(dic2)    #字典

abc  = {"k":1,"k1":2}
f = open('pickle_file','wb')
pickle.dump(abc,f)
f.close()

f = open('pickle_file','rb')
struct_time2 = pickle.load(f)
print(abc["k"])

5.3、shelve也是python提供給我們的序列化工具,比pickle用起來更簡單一些。shelve只提供給我們一個open方法,是用key來訪問的,使用起來和字典類似

import shelve
f1 = shelve.open('shelve_file')
f1['k1']={'name':'jump','age':18,'job':['php','smoking']}  #寫
print(f1['k1']['job'])  #取  ['php', 'smoking']
f1.close()

5.4、XML是實現不同語言或程式之間進行資料交換的協議,XML檔案格式如下:

<data>
    <city name="bj">
        <rank updated="yes">1</rank>
        <year>2018</year>
        <gdppc>141100</gdppc>
    </city>
    <city name="nj">
        <rank updated="yes">5</rank>
        <year>2018</year>
        <gdppc>59900</gdppc>
    </city>
    <city name="sh">
        <rank updated="yes">2</rank>
        <year>2018</year>
        <gdppc>13600</gdppc>
    </city>
</data>

XML操作:

import xml.etree.ElementTree as ET
tree= ET.parse(filename)  #解析檔案
root=tree.getroot()  #獲取根節點
root.tag  #根標籤名稱

for child in root:
    print(child.tag, child.attrib) # 子節點的標籤名稱和標籤屬性
    
    for i in child:   #遍歷XML文件的第三層
        print(i.tag,i.text)  # 二級節點的標籤名稱和內容

for i in root.iter("xxx"):   #遍歷根節點下面的所有xxx節點,然後修改
       xx=int(i.text)+1
       i.text=str(xx) 
       i.set("k",'v')   #設定屬性
       del node.attrib['k']  #刪除
tree.write("filename")  #儲存檔案

for  i in root.findall("city"):
       xx = int(city.find("rank").text)
       if xx>3:
           root.remove(city)  #刪除排名大於3的

 XML檔案建立

import xml.etree.ElementTree as ET
new_xml=ET.Element("xxx")  #建立根節點
name=ET.SubElement(new_xml,"name",attrib={"k":"v"})  #建立子節點
age=ET.SubElement(name,"age",attrib={"k1":"v1"})  #建立二級子節點
age.text = "22"   #給節點定義值
et=ET.ElementTree(new_xml) #生成文件物件
et.write("abc.xml",encoding="utf8")  #建立xml檔案

  

六、檔案及加密相關

6.1、configparser

configparser用於處理特定格式的檔案,該模組適用於配置檔案的格式與windows ini檔案類似,可以包含一個或多個節(section),每個節可以有多個引數(鍵=值)

配置檔案形式(mysql)

[client]
port = 3306
[mysqld]
port = 3306
datadir=D:\websoft\mysql-5.6.15\data
basedir=D:\websoft\mysql-5.6.15
max_connections=500
performance_schema=0
key_buffer = 16M
max_allowed_packet = 1M
#table_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M
slow_query_log_file=D:\websoft\mysql-5.6.15\log\slow.log

建立一個配置檔案:

import configparser 
config= configparser.ConfigParser()  #新建物件
config["Name"] ={'server':'hostname','IP':'111'}  #Name節點下sever和IP
with open("config.conf","w")as f:   #建立配置檔案
      config.write(f)

增刪改查操作:

import configparser
config= configparser.ConfigParser()
config.read("config.conf")   #開啟配置檔案
print(config.sections()) #獲取所有的節點名稱

print(config["Name"]["server"])  #獲取Name節點下server的值
print(config.options("Name2"))   #獲取Name2節點下的鍵
print(config.items("Name"))    #獲取Name節點下所有的鍵值對
print(config.get("Name","server"))  #獲取Name 節點下server 的值

has_sec = config.has_section('section1')
print(has_sec)           #判斷是否包含section1這個節點,返回False/True

config.add_section("section1")
config.write(open('config.conf', 'w'))  #增加一個節點section1
config.remove_section("section1")       
config.write(open('config.conf', 'w'))    #刪除一個節點section1

config.set('section1', 'k10', "123")  
config.write(open('config.conf', 'w'))   #將section1節點下的k10設定為123
config.remove_option('section1', 'k10')
config.write(open('config.conf', 'w'))    #將section1節點下的k10刪除

config.has_option('section1', 'k10') #檢查section節點下k10是否存在,返回False/True

6.2、shutil 高階的 檔案、資料夾、壓縮包 處理模組

import shutil

# shutil.copyfileobj(fsrc, fdst[, length]) 將檔案內容拷貝到另一個檔案中
shutil.copyfileobj(open('oldfilename','r'), open('newfilename', 'w'))

#shutil.copyfile(src, dst)  拷貝檔案,目標檔案無需存在
shutil.copyfile('f1', 'f2')

#shutil.copymode(src, dst)僅拷貝許可權。內容、組、使用者均不變
shutil.copymode('f1', 'f2') #目標檔案必須存在

#shutil.copystat(src, dst)僅拷貝檔案狀態的資訊
shutil.copystat('f1', 'f2') #目標檔案必須存在

#shutil.copy2(src, dst) 拷貝檔案和狀態資訊
shutil.copy2('f1', 'f2')

#shutil.copy(src, dst) 拷貝檔案和許可權
shutil.copy('f1', 'f2')

#shutil.ignore_patterns(*patterns)
#shutil.copytree(src, dst, symlinks=False, ignore=None)
#遞迴的去拷貝資料夾
shutil.copytree('dir1', 'dir2', ignore=shutil.ignore_patterns('*.txt')) 
#目標目錄不能存在,注意對dir2目錄父級目錄要有可寫許可權,ignore的意思是排除 

#shutil.rmtree(path[, ignore_errors[, onerror]])
#遞迴的去刪除資料夾
shutil.rmtree('dir1')

#shutil.move(src, dst)
#遞迴的去移動檔案,它類似mv命令,其實就是重新命名。
shutil.move('dir1', 'dir3')

#shutil.make_archive(base_name, format,...)  壓縮檔案
#base_name: 壓縮包的檔名,也可以是壓縮包的路徑
#format:壓縮包種類,“zip”, “tar”, “bztar”,“gztar”
#root_dir:要壓縮的資料夾路徑(預設當前目錄)
shutil.make_archive("/bak/data_bak", 'zip', root_dir='/data')

#shutil 對壓縮包的處理是呼叫 ZipFile 和 TarFile 兩個模組來進行的,如下:
import zipfile
# 壓縮
z = zipfile.ZipFile('bak.zip', 'w')
z.write('1.txt')
z.write('2.txt')
z.close()
# 解壓
z = zipfile.ZipFile('bak.zip', 'r')
z.extractall(path='.')
z.close()

import tarfile
tar = tarfile.open('your.tar','w')  # 建立一個壓縮包
tar.add('/Users/bbs2.log', arcname='bbs2.log')  # 將檔案新增到壓縮包並命名
tar.add('/Users/cmdb.log', arcname='cmdb.log')  
tar.close()  # 關閉壓縮包
# 解壓
tar = tarfile.open('your.tar','r')  # 開啟一個壓縮包
tar.extractall()  # 解壓包內所有檔案(可設定解壓地址)
tar.close()  # 關閉壓縮包

6.3、hashlib

用於加密相關的操作,代替了md5模組和sha模組,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 演算法

import hashlib
obj=hashlib.md5()  #建立一個物件
obj.update("hello".encode("utf-8"))  #加密
print(obj.hexdigest()) #5d41402abc4b2a76b9719d911017c592 (十六進位制)
print(obj.digest)

以上加密演算法雖然依然非常厲害,但時候存在缺陷,即:通過撞庫可以反解。所以,有必要對加密演算法中新增自定義key再來做加密。

import hashlib
obj=hashlib.md5("jump".encode("utf8"))  #加自定義key
obj.update("hello".encode("utf-8"))
print(obj.hexdigest())   #b455addaf0e23904477ba8db951f3edc

 

七、 re  正則

正則就是用一些具有特殊含義的符號組合到一起(稱為正則表示式)來描述字元或者字串的方法。或者說:正則就是用來描述一類事物的規則。(在Python中)它內嵌在Python中,並通過 re 模組實現。正則表示式模式被編譯成一系列的位元組碼,然後由用 C 編寫的匹配引擎執行

元字元
 
匹配內容
\w 匹配字母(包含中文)或數字或下劃線
\W 匹配非字母(包含中文)或數字或下劃線
\s 匹配任意的空白符
\S 匹配任意非空白符
\d 匹配數字
\D 匹配非數字
\A 從字串開頭匹配
\z 匹配字串的結束,如果是換行,只匹配到換行前的結果
\Z 匹配字串的結束
\n 匹配一個換行符
\t 匹配一個製表符
^ 匹配字串的開始
$ 匹配字串的結尾
. 匹配任意字元,除了換行符,當re.DOTALL標記被指定時,則可以匹配包括換行符的任意字元。
[...] 匹配字元組中的字元
[^...] 匹配除了字元組中的字元的所有字元
* 匹配0個或者多個左邊的字元。
+ 匹配一個或者多個左邊的字元。
匹配0個或者1個左邊的字元,非貪婪方式。
{n} 精準匹配n個前面的表示式。
{n,m} 匹配n到m次由前面的正則表示式定義的片段,貪婪方式
a|b 匹配a或者b。
() 匹配括號內的表示式,也表示一個組

7.1、常用方法舉例

import re
#findall 全部找到返回一個列表
#findall(pattern, string, flags=0)
print(re.findall("a","abcdabcdaa")) #['a', 'a', 'a', 'a']

#search 只到找到第一個匹配然後返回一個包含匹配資訊的物件,該物件可以通過呼叫group()方法得到匹配的字串,如果字串沒有匹配,則返回None。
# search(pattern, string, flags=0)
print(re.search("a","abcdabcdaa").group())  #a
print(re.search("a","abcdabcdaa"))   #<_sre.SRE_Match object; span=(0, 1), match='a'>

#match 同search,不過在字串開始處進行匹配,完全可以用search+^代替match
#match(pattern, string, flags=0)
# pattern: 正則模型
# string : 要匹配的字串
# falgs  : 匹配模式
print(re.match('e','ebcdh').group())  #e
print(re.match('e','ebcdh'))   #<_sre.SRE_Match object; span=(0, 1), match='e'>

#split 分割 可按照任意分割符進行分割
#split(pattern, string, maxsplit=0, flags=0)
# pattern: 正則模型
# string : 要匹配的字串
# maxsplit:指定分割個數
# flags  : 匹配模式
print(re.split('[ab]','abcd'))     #['', '', 'cd'],先按'a'分割得到''和'bcd',再對''和'bcd'分別按'b'分割

#sub 替換
#sub(pattern, repl, string, count=0, flags=0)
# pattern: 正則模型
# repl   : 要替換的字串或可執行物件
# string : 要匹配的字串
# count  : 指定匹配個數
# flags  : 匹配模式
r = re.sub("\d+", "999", "123abcd456edcf789", 2)
print(r)  #999abcd999edcf789

#re.compile()
obj = re.compile("\d+")
print(obj.search("abcd123efg456yhn789").group())
print(obj.findall("abcd123efg456yhn789"))

#返回123 和['123', '456', '789']

7.2、命名分組

print(re.search("(?P<tag_name>\w+)","abcd"))
#(?P<name>) 分組固定格式

print((re.search("(?P<tag_name>\w+)","abcd").group("tag_name")))
#取分組值


print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>").group())
print(re.findall("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>"))
#返回的結果為:<h1>hello</h1>和[h1]
#group的作用是將所有組拼接到一起顯示出來
#findall結果是組內的結果,且是最後一個組的結果

 

八、logging 用於便捷記錄日誌且執行緒安全的模組(日誌模組)

日誌等級:

CRITICAL = 50  #FATAL = CRITICAL
ERROR = 40
WARNING = 30  #WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0 #不設定
import logging

logging.debug('除錯debug')
logging.info('訊息info')
logging.warning('警告warn')
logging.error('錯誤error')
logging.critical('嚴重critical')

#返回結果:
"""WARNING:root:警告warn
ERROR:root:錯誤error
CRITICAL:root:嚴重critical"""

#預設級別為warning,預設列印到終端

8.1、單檔案日誌

import logging  
logging.basicConfig(level=logging.DEBUG,  
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
                    datefmt='%a, %d %b %Y %H:%M:%S',  
                    filename='1.log',  
                    filemode='w')  
  
logging.debug('debug message')  
logging.info('info message')  
logging.warning('warning message')  
logging.error('error message')  
logging.critical('critical message')

 執行結果:

相關引數詳情:

logging.basicConfig()函式中可通過具體引數來更改logging模組預設行為,可用引數有:

filename:用指定的檔名建立FiledHandler,這樣日誌會被儲存在指定的檔案中。
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引數會被忽略。
logging.StreamHandler()   #列印到桌面

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使用者輸出的訊息

8.2、多檔案日誌

import  logging
#定義正確輸出日誌
run_log = logging.FileHandler('run.log', 'a', encoding='utf-8')
fmt = logging.Formatter(fmt="%(asctime)s  - %(levelname)s :  %(message)s")
run_log.setFormatter(fmt)
logger_info = logging.Logger('run_log', level=logging.INFO)
logger_info.addHandler(run_log)

#定義錯誤輸出日誌
error_log = logging.FileHandler('error.log', 'a', encoding='utf-8')
fmt = fmt = logging.Formatter(fmt="%(asctime)s  - %(levelname)s :  %(message)s")
error_log.setFormatter(fmt)
logger_error = logging.Logger('error_log', level=logging.ERROR)
logger_error.addHandler(error_log)

logger_info.info("xxx")
logger_error.error("yyy")

執行結果:

這樣在後續的使用中我們可以通過定義函式(或者類)來按需呼叫 即可

 

九、補充

9.1、paramiko 模組

paramiko是一個用於做遠端控制的模組,使用該模組可以對遠端伺服器進行命令或檔案操作,值得一說的是,fabric和ansible內部的遠端管理就是使用的paramiko來現實的。

#下載安裝
#pycrypto,由於 paramiko 模組內部依賴pycrypto,所以先下載安裝pycrypto
pip3 install pycrypto
pip3 install paramiko
#執行命令列印結果

# 使用者名稱密碼方式
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.1.50', 22, 'root', '1234')
stdin, stdout, stderr = ssh.exec_command('df')
print (stdout.read())
ssh.close()

#祕鑰方式
private_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(private_key_path)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('主機名 ', 埠, '使用者名稱', key)
stdin, stdout, stderr = ssh.exec_command('df')
print (stdout.read())
ssh.close()
#上傳下載檔案


#使用者名稱、密碼方式
import os,sys
import paramiko
t = paramiko.Transport(('192.168.1.50',22))
t.connect(username='root',password='123')
sftp.put('test.py','/test.py')   #上傳
sftp.get('/test.py','/test2.py')  #下載
t.close()

#祕鑰方式
pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)
t = paramiko.Transport(('192.168.1.50',22))
t.connect(username='root',pkey=key)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('test3.py','/tmp/test3.py')    #上傳
sftp.get('/tmp/test3.py','/test4.py')    #下載
t.close()

9.2、Requests模組 是使用 Apache2 Licensed 許可證的 基於Python開發的HTTP 庫,其在Python內建模組的基礎上進行了高度的封裝,從而使得進行網路請求時,變得美好了許多,使用Requests可以輕而易舉的完成瀏覽器可有的任何操作。(ython標準庫中提供了:urllib等模組以供Http請求,但是,它的 API 太渣了)

#安裝模組
pip3 install requests
# 1、無引數例項
import requests
ret = requests.get('https://www.baidu.com')
print(ret.url)
# 2、有引數例項
payload = {'key1': 'value1', 'key2': 'value2'}
ret = requests.get("http://www.baidu.com", params=payload)
print(ret.url)

#返回結果
#https://www.baidu.com/
#http://www.baidu.com/?key1=value1&key2=value2
# 1、基本POST提交
import requests
data = {'key1': 'value1', 'key2': 'value2'}
ret = requests.post("http://www.baidu.com", data=payload)
print(ret.text)
 
 
# 2、傳送請求頭和資料
import json
url = 'https://www.baidu.com'
data = {'k': 'v'}
headers = {'content-type': 'application/json'}
ret = requests.post(url, data=json.dumps(data), headers=headers)

例項:1、檢視火車停靠資訊及時間  2、檢視城市的天氣預報

#1、檢視去上海的G7021號火車的停靠資訊及時間
r = requests.get('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=G7021&UserID=')
result = r.text
# 解析XML格式內容
root = ET.XML(result)
for node in root.iter('TrainDetailInfo'):
    print(node.find('TrainStation').text,node.find("ArriveTime").text,node.find("StartTime").text)


#2、檢視上海的天氣預報
r = requests.get('http://ws.webxml.com.cn/WebServices/WeatherWS.asmx/getWeather?theCityCode=上海&theUserID=')
result = r.text
# 解析XML格式內容
root=ET.XML(result)
for node in root:
    print(node.text)

執行結果:

Ps:更多介面可以檢視  http://www.webxml.com.cn/zh_cn/web_services.aspx

9.3、suprocess 模組用於執行系統相關命令返回結果

#call 執行命令,返回狀態碼
ret = subprocess.call(["ls", "-l"], shell=False)
ret = subprocess.call("ls -l", shell=True)

#check_call執行命令,如果執行狀態碼是 0 ,則返回0,否則拋異常
subprocess.check_call(["ls", "-l"])
subprocess.check_call("exit 1", shell=True)

#check_output執行命令,如果狀態碼是 0 ,則返回執行結果,否則拋異常
subprocess.check_output(["echo", "Hello World!"])
subprocess.check_output("exit 1", shell=True)

#subprocess.Popen(...) 用於執行復雜的系統命令

obj = subprocess.Popen('dir',
                 shell=True,
                 stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE,       
                )
print(obj.stdout.read().decode('utf-8'))  # 正確命令
print(obj.stderr.read().decode('utf-8'))  # 錯誤命令

# shell: 命令直譯器,相當於呼叫cmd 執行指定的命令
# stdout:正確結果丟到管道中。
# stderr:錯了丟到另一個管道中

subprocess.Popen()引數說明:

  • args:shell命令,可以是字串或者序列型別(如:list,元組)
  • bufsize:指定緩衝。0 無緩衝,1 行緩衝,其他 緩衝區大小,負值 系統緩衝
  • stdin, stdout, stderr:分別表示程式的標準輸入、輸出、錯誤控制代碼
  • preexec_fn:只在Unix平臺下有效,用於指定一個可執行物件(callable object),它將在子程序執行之前被呼叫
  • close_sfs:在windows平臺下,如果close_fds被設定為True,則新建立的子程序將不會繼承父程序的輸入、輸出、錯誤管道。
    所以不能將close_fds設定為True同時重定向子程序的標準輸入、輸出與錯誤(stdin, stdout, stderr)。
  • shell:同上
  • cwd:用於設定子程序的當前目錄
  • env:用於指定子程序的環境變數。如果env = None,子程序的環境變數將從父程序中繼承。
  • universal_newlines:不同系統的換行符不同,True -> 同意使用 \n
  • startupinfo與createionflags只在windows下有效
    將被傳遞給底層的CreateProcess()函式,用於設定子程序的一些屬性,如:主視窗的外觀,程序的優先順序等等