常用模塊:
一、time模塊
二、datetime模塊
三、sys 模塊
四、os 模塊
五、random 模塊
六、shutil 模塊
七、json, pickle , shelve模塊
八、xml 模塊
九、configparer模塊
十、hashlib模塊
十一、re模塊
十二、logging模塊
十三、subprocess
一、time模塊
import time
# s = time.time()
# print(s)
# time.sleep(2)
# 拿到format string的方式
# print(time.ctime(s)) # time.ctime(float) ----> format string in local time
# print(time.asctime(time.localtime(s))) # time.asctime(tuple) ----> format string in local time
# print(time.asctime()) # 如果不傳值,默認的就會用當前的時間戳
# print(time.ctime()) # 如果不傳值,默認的就會用當前的struct time
# print(time.localtime())
# print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())) # 按照給定的格式 將 tuple---> string, strptime 是 string parse time 的縮寫,就是將字串決議成元組的意思,
Commonly used format codes:
%Y Year with century as a decimal number.
%m Month as a decimal number [01,12].
%d Day of the month as a decimal number [01,31].
%H Hour (24-hour clock) as a decimal number [00,23].
%M Minute as a decimal number [00,59].
%S Second as a decimal number [00,61].
%z Time zone offset from UTC.
%a Locale's abbreviated weekday name.
%A Locale's full weekday name.
%b Locale's abbreviated month name.
%B Locale's full month name.
%c Locale's appropriate date and time representation.
%I Hour (12-hour clock) as a decimal number [01,12].
%p Locale's equivalent of either AM or PM.
# 拿到時間戳 float 型別
# tu = time.localtime()
# print(tu)
# s = time.mktime(tu) # time.mktime() 將 tuple----> float
# print(time.time())
# 拿到struct time 型別
# s = time.time()
# print(time.localtime(s)) # 北京時間 接受float ---> tuple
# print(time.gmtime(s)) # 天文臺時間 接受float ---> tuple
The other representation is a tuple of 9 integers giving local time.
The tuple items are:
year (including century, e.g. 1998)
month (1-12)
day (1-31)
hours (0-23)
minutes (0-59)
seconds (0-59)
weekday (0-6, Monday is 0)
Julian day (day in the year, 1-366)
DST (Daylight Savings Time) flag (-1, 0 or 1)
If the DST flag is 0, the time is given in the regular time zone;
if it is 1, the time is given in the DST time zone;
if it is -1, mktime() should guess based on the date and time.
# print(time.strptime(time.ctime())) # 接受 string ---> tuple, strftime 是 string format time 的縮寫 就是轉成字串時間的意思
# print(time.strptime(time.asctime())) # 接受 string ---> tuple

二、datetime模塊
在python檔案中,time是歸類在常規作業系統服務中,它提供的功能更加接近于作業系統層面,其所能表述的日期范圍被限定在1970-2038之間,如果需要表述范圍之外的日期,可能需要考慮使用datetime模塊更好,
datetime比time高級了不少,可以理解為datetime基于time進行了封裝,提供了更多實用的函式,主要包含一下幾類:
- timedelta:主要用于計算時間跨度
- tzinfo:時區相關
- time:只關注時間
- date:只關注日期
- datetime:同時有時間和日期
在實際使用中,用得比較多的是datetime.datetime和datetime.timedelta,另外兩個datetime.date和datetime.time實際使用和datetime.datetime并無太大差別,datetime.datetime 主要會有以下屬性及常用方法:
datetime.datetime.ctime() 將datetime.datetime型別轉化成str型別,輸出:Sun Jul 28 15:47:51 2019
datetime.datetime.now():回傳當前系統時間:2019-07-28 15:42:24.765625
datetime.datetime.now().date():回傳當前日期時間的日期部分:2019-07-28
datetime.datetime.now().time():回傳當前日期時間的時間部分:15:42:24.750000
datetime.datetime.fromtimestamp()
datetime.datetime.replace()
datetime.datetime.strftime():由日期格式轉化為字串格式
datetime.datetime.now().strftime('%b-%d-%Y %H:%M:%S')
'Apr-16-2017 21:01:35'
datetime.datetime.strptime():由字串格式轉化為日期格式
datetime.datetime.strptime('Apr-16-2017 21:01:35', '%b-%d-%Y %H:%M:%S')
2017-04-16 21:01:35
除了實體本身具有的方法,類本身也提供了很多好用的方法:
- datetime.strptime(date_string,format): 給定時間格式決議字串
- datetime.now([tz]):當前時間默認 localtime
- datetime.today():當前時間
datetime.timedelta用來計算兩個datetime.datetime或者datetime.date型別之間的時間差,
>>> a=datetime.datetime.now()
>>> b=datetime.datetime.now()
>>> a
datetime.datetime(2017, 4, 16, 21, 21, 20, 871000)
>>> b
datetime.datetime(2017, 4, 16, 21, 21, 29, 603000)
>>> b-a
datetime.timedelta(0, 8, 732000)
>>> (b-a).seconds
8
或者
time1 = datetime.datetime(2016, 10, 20)
time2 = datetime.datetime(2015, 11, 2)
"""計算天數差值"""
print(time1-time2).days
"""計算兩個日期之間相隔的秒數"""
print (time1-time2).total_seconds()
import datetime, time # 用于時間加減
print(datetime.datetime.now()) # 回傳 2020-08-01 16:15:58.512076
print(datetime.date.fromtimestamp(time.time())) # 時間戳直接轉成日期格式 2019-01-01
print(datetime.datetime.now() + datetime.timedelta(3)) # 當前時間+3天 2019-01-04 00:56:58.771296
print(datetime.datetime.now() + datetime.timedelta(-3)) # 當前時間-3天 2018-12-29 00:56:58.771296
print(datetime.datetime.now() + datetime.timedelta(hours=3)) # 當前時間+3小時 2019-01-01 03:56:58.771296
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) # 當前時間+30分 2019-01-01 01:26:58.771296
c_time = datetime.datetime.now()
print(c_time.replace(minute=3, hour=2)) # 時間替換 2019-01-01 02:03:58.771296
列印進度條
import time
def progress(percent):
'''列印進度條'''
if percent > 1:
percent = 1
res = int(50 * percent) * 'I'
print('\r[%-50s] %d%%' % (res, int(100 * percent)), end='')
recv_size=0
total_size=1025
while recv_size < total_size:
time.sleep(0.01) # 下載了1024個位元組的資料
recv_size+=1024 # recv_size=2048
# 列印進度條
percent = recv_size / total_size # 1024 / 333333
progress(percent)
三、sys 模塊
import sys sys.argv #在命令列引數是一個空串列,在其他中第一個串列元素中程式本身的路徑 sys.exit(0) #退出程式,正常退出時exit(0) sys.version #獲取python解釋程式的版本資訊 sys.path #回傳模塊的搜索路徑,初始化時使用python PATH環境變數的值 sys.platform #回傳作業系統平臺的名稱 sys.stdin #輸入相關 standard input 標準輸入 sys.stdout #輸出相關 standard output 標注輸出 sys.stderror #錯誤相關 sys.getrecursionlimit() #獲取最大遞回層數 1000 sys.setrecursionlimit(5000) #設定最大遞回層數
四、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[, ...]]) 將多個路徑組合后回傳,第一個絕對路徑之前的引數將被忽略
print(os.path.join("D:\\python\\wwww","aaa")) #做路徑拼接用的 #D:\python\wwww\aaa
print(os.path.join(r"D:\python\wwww","aaa")) #做路徑拼接用的 #D:\python\wwww\aaa
os.path.getatime(path) 回傳path所指向的檔案或者目錄的最后存取時間
os.path.getmtime(path) 回傳path所指向的檔案或者目錄的最后修改時間
os.path.getsize(path) 回傳path的大小
在Linux和Mac平臺上,該函式會原樣回傳path,在windows平臺上會將路徑中所有字符轉換為小寫,并將所有斜杠轉換為反斜杠,
>>> os.path.normcase('c:/windows\\system32\\')
'c:\\windows\\system32\\'
規范化路徑,如..和/
>>> os.path.normpath('c://windows\\System32\\../Temp/')
'c:\\windows\\Temp'
>>> a='/Users/jieli/test1/\\\a1/\\\\aa.py/../..'
>>> print(os.path.normpath(a))
/Users/jieli/test1
os路徑處理
#方式一:推薦使用
import os
#具體應用
import os,sys
possible_topdir = os.path.normpath(os.path.join(
os.path.abspath(__file__),
os.pardir, #上一級
os.pardir,
os.pardir
))
sys.path.insert(0,possible_topdir)
#方式二:不推薦使用
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
五、random 模塊
# 隨機生成
import random
print(random.random()) # (0,1)----float 大于0且小于1之間的小數
print(random.randint(1, 3)) # [1,3] 大于等于1且小于等于3之間的整數
print(random.randrange(1, 3)) # [1,3) 大于等于1且小于3之間的整數
print(random.choice([1, '23', [4, 5]])) # 1或者23或者[4,5]
print(random.sample([1, '23', [4, 5]], 2)) # 串列元素任意2個組合
print(random.uniform(1, 3)) # 大于1小于3的小數,如1.927109612082716
item = [1, 3, 5, 7, 9]
random.shuffle(item) # 打亂item的順序,相當于"洗牌"
print(item)
# 隨機生成驗證碼
import random
def make_code(n):
res = ''
for i in range(n):
alf = chr(random.randint(65, 90))
num = str(random.randint(0, 9))
res += random.choice([alf, num])
return res
print(make_code(6))
------------------------------------------------------------->
import random, string
source = string.digits + string.ascii_lowercase + string.ascii_uppercase + string.ascii_letters
print(source)
# 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
print("".join(random.sample(source, 6)))
六、shutil 模塊
高級的 檔案,檔案夾,壓縮包處理模塊
shutil.copyfileobj(fsrc, fdst[, length])
將檔案內容拷貝到另一個檔案中
shutil.copyfile(src, dst)
拷貝檔案,
shutil.copymode(src, dst)
僅拷貝權限,內容、組、用戶均不變
shutil.copystat(src, dst)
僅拷貝狀態的資訊,包括:mode bits, atime, mtime, flags
shutil.copy(src, dst)
拷貝檔案和權限
shutil.copy2(src, dst)
拷貝檔案和狀態資訊
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
遞回的去拷貝檔案夾
shutil.move(src, dst)
遞回的去移動檔案,它類似mv命令,其實就是重命名,
"""
shutil.copyfileobj(open('xmltest.xml','r'), open('new.xml', 'w'))
shutil.copyfile('b.txt', 'bnew.txt')#目標檔案無需存在
shutil.copymode('f1.log', 'f2.log') #目標檔案必須存在
shutil.copystat('f1.log', 'f2.log') #目標檔案必須存在
shutil.copy('f1.log', 'f2.log')
shutil.copy2('f1.log', 'f2.log')
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目標目錄不能存在,注意對folder2目錄父級目錄要有可寫權限,ignore的意思是排除
'''
通常的拷貝都把軟連接拷貝成硬鏈接,即對待軟連接來說,創建新的檔案
'''
#拷貝軟連接
shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
shutil.move('folder1', 'folder3')
"""
shutil.make_archive(base_name, format,...)
創建壓縮包并回傳檔案路徑,例如:zip、tar
base_name: 壓縮包的檔案名,也可以是壓縮包的路徑,只是檔案名時,則保存至當前目錄,否則保存至指定路徑,
如 data_bak =>保存至當前路徑
如:/tmp/data_bak =>保存至/tmp/
format: 壓縮包種類,“zip”, “tar”, “bztar”,“gztar”
root_dir: 要壓縮的檔案夾路徑(默認當前目錄)
owner: 用戶,默認當前用戶
group: 組,默認當前組
logger: 用于記錄日志,通常是logging.Logger物件
"""
# 將 /data 下的檔案打包放置當前程式目錄
import shutil
ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
# 將 /data下的檔案打包放置 /tmp/目錄
import shutil
ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')
#shutil 對壓縮包的處理是呼叫 ZipFile 和 TarFile 兩個模塊來進行的,詳細:
#zipfile壓縮解壓縮
import zipfile
# 壓縮
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()
# 解壓
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall(path='.')
z.close()
#tarfile壓縮解壓縮
import tarfile
# 壓縮
t=tarfile.open('/tmp/egon.tar','w')
t.add('/test1/a.py',arcname='a.bak')
t.add('/test1/b.py',arcname='b.bak')
t.close()
# 解壓
t=tarfile.open('/tmp/egon.tar','r')
t.extractall('/egon')
t.close()
七、json, pickle 模塊
1.什么是序列化?
序列化指的是把記憶體的資料型別轉換成一個特定的格式的內容
該格式的內容可以用于存盤或者傳輸給其他平臺使用
與序列化想對應的逆操作是返序列化,
記憶體中的資料型別 -----》 序列化 ------》特定的格式 (json 或者pickle格式)
記憶體中的資料型別《----- 反序列化《------ 特定的格式 (json 或者pickle格式)
{‘a':111} -----》 序列化 str({‘a':111}) ------》"{‘a':111} "
{‘a':111}《----- 反序列化 eval("{‘a':111} ")《------ "{‘a':111} "
3.為何要有序列化?
序列化得到結果---》特定的格式的內容有兩種用途 (可以用于存盤,可以傳輸給其他平臺使用)
pickle 只能識別Python的資料格式,如果只是存檔的話,建議使用pickle
json是通用的,json格式兼容的是所有語言通用的資料型別,不能識別某一語言的所獨有的型別,跨平臺資料互動的話可用json
- JSON表示的物件就是標準的JavaScript語言的物件,JSON和Python內置的資料型別對應如下:

4.如何實作序列化
import json
# 序列化
json_res=json.dumps([1,'aaa',True,False])
# print(json_res,type(json_res)) # "[1, "aaa", true, false]"
# 反序列化
l=json.loads(json_res)
print(l,type(l))
# 序列化的結果寫入檔案的復雜方法
json_res=json.dumps([1,'aaa',True,False])
with open('test.json',mode='wt',encoding='utf-8') as f:
f.write(json_res)
# 將序列化的結果寫入檔案的簡單方法
with open('test.json',mode='wt',encoding='utf-8') as f:
json.dump([1,'aaa',True,False],f)
# 從檔案讀取json格式的字串進行反序列化操作的復雜方法
with open('test.json',mode='rt',encoding='utf-8') as f:
json_res=f.read()
l=json.loads(json_res)
print(l,type(l))
# 從檔案讀取json格式的字串進行反序列化操作的簡單方法
with open('test.json',mode='rt',encoding='utf-8') as f:
l=json.load(f)
print(l,type(l))
# 4、猴子補丁
# 在入口處打猴子補丁
import json
import ujson
def monkey_patch_json():
json.__name__ = 'ujson'
json.dumps = ujson.dumps # 在自己寫好的 ujson 模塊中,有更好的dumps 方法,以后呼叫json.dumps 其實就是在參考ujson.dump
json.loads = ujson.loads
monkey_patch_json() # 在入口檔案出運行
print(json.loads)
json.loads = 'bbb'
print(json.loads)
import pickle
pickle 和 json 用法一樣
dic = {'name': 'tom', '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 = https://www.cnblogs.com/Teyisang/p/pickle.loads(f.read()) # 等價于data=pickle.load(f)
print(data['age'])
shelve模塊比pickle模塊簡單,只有一個open函式,回傳類似字典的物件,可讀可寫;key必須為字串,而值可以是python所支持的
import shelve
f=shelve.open(r'sheve.txt')
#存
# f['stu1_info']={'name':'rose','age':18,'hobby':['sing','talk','swim']}
# f['stu2_info']={'name':'tom','age':53}
#取
print(f['stu1_info']['hobby'])
f.close()
八、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資料
xml協議在各個語言里的都 是支持的,在python中可以用以下模塊操作xml:
# print(root.iter('year')) #全文搜索
# print(root.find('country')) #在root的子節點找,只找一個
# print(root.findall('country')) #在root的子節點找,找所有
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,child.attrib['name'])
for i in child:
print(i.tag,i.attrib,i.text)
#只遍歷year 節點
for node in root.iter('year'):
print(node.tag,node.text)
#---------------------------------------
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
node.text=str(new_year)
node.set('updated','yes')
node.set('version','1.0')
tree.write('test.xml')
#洗掉node
for country in root.findall('country'):
rank = int(country.find('rank').text)
if rank > 50:
root.remove(country)
tree.write('output.xml')
View Code
#在country內添加(append)節點year2
import xml.etree.ElementTree as ET
tree = ET.parse("a.xml")
root=tree.getroot()
for country in root.findall('country'):
for year in country.findall('year'):
if int(year.text) > 2000:
year2=ET.Element('year2')
year2.text='新年'
year2.attrib={'update':'yes'}
country.append(year2) #往country節點下添加子節點
tree.write('a.xml.swap')
View Code
自己創建xml檔案:
import xml.etree.ElementTree 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) #列印生成的格式
View Code
xml教程的:點擊
九、configparser 模塊
configparser用于處理特定格式的檔案,本質上是利用open來操作檔案,主要用于組態檔分析用的
該模塊適用于組態檔的格式與windows ini檔案類似,可以包含一個或多個節(section),每個節可以有多個引數(鍵=值),
# 注釋1 ; 注釋2 [section1] k1 = v1 k2:v2 user=egon age=18 is_admin=true salary=31 [section2] k1 = v1組態檔
""" 讀取 """ import configparser config = configparser.ConfigParser() config.read('a.cfg') # 查看所有的標題 res = config.sections() # ['section1', 'section2'] print(res) # 查看標題section1下所有key=value的key options = config.options('section1') print(options) # ['k1', 'k2', 'user', 'age', 'is_admin', 'salary'] # 查看標題section1下所有key=value的(key,value)格式 item_list = config.items('section1') print( item_list) # [('k1', 'v1'), ('k2', 'v2'), ('user', 'egon'), ('age', '18'), ('is_admin', 'true'), ('salary', '31')] # 查看標題section1下user的值=>字串格式 val = config.get('section1', 'user') print(val) # egon # 查看標題section1下age的值=>整數格式 val1 = config.getint('section1', 'age') print(val1) # 18 # 查看標題section1下is_admin的值=>布林值格式 val2 = config.getboolean('section1', 'is_admin') print(val2) # True # 查看標題section1下salary的值=>浮點型格式 val3 = config.getfloat('section1', 'salary') print(val3) # 31.0 """ 改寫 """ import configparser config = configparser.ConfigParser() config.read('a.cfg', encoding='utf-8') # 洗掉整個標題section2 config.remove_section('section2') # 洗掉標題section1下的某個k1和k2 config.remove_option('section1', 'k1') config.remove_option('section1', 'k2') # 判斷是否存在某個標題 print(config.has_section('section1')) # 判斷標題section1下是否有user print(config.has_option('section1', '')) # 添加一個標題 config.add_section('egon') # 在標題egon下添加name=egon,age=18的配置 config.set('egon', 'name', 'egon') # config.set('egon','age',18) #報錯,必須是字串 # 最后將修改的內容寫入檔案,完成最終的修改 config.write(open('a.cfg', 'w')) """ 基于上述方法添加一個ini檔案 """ 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' # mutates the parser topsecret['ForwardX11'] = 'no' # same here config['DEFAULT']['ForwardX11'] = 'yes' with open('example.ini', 'w') as configfile: config.write(configfile)讀取,改寫,新建
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' # mutates the parser topsecret['ForwardX11'] = 'no' # same here config['DEFAULT']['ForwardX11'] = 'yes' with open('example.ini', 'w') as configfile: config.write(configfile)基于上述方法添加一個ini檔案
十、hashlib 模塊
hash是一種演算法(3.x里代替了md5模塊和sha模塊,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 演算法),該演算法接受傳入的內容,經過運算得到一串hash值
hash值的特點是
- 只要傳入的內容一樣,得到的hash值必然一樣
- 不能由hash值返解成內容,不應該在網路傳輸明文密碼
- 只要使用的hash演算法不變,無論校驗的內容有多大,得到的hash值長度是固定的
1、演算法介紹
Python的hashlib提供了常見的摘要演算法,如MD5,SHA1等等,
什么是摘要演算法呢?摘要演算法又稱哈希演算法、散列演算法,它通過一個函式,把任意長度的資料轉換為一個長度固定的資料串(通常用16進制的字串表示),
摘要演算法就是通過摘要函式f()對任意長度的資料data計算出固定長度的摘要digest,目的是為了發現原始資料是否被人篡改過,
摘要演算法之所以能指出資料是否被篡改過,就是因為摘要函式是一個單向函式,計算f(data)很容易,但通過digest反推data卻非常困難,而且,對原始資料做一個bit的修改,都會導致計算出的摘要完全不同,
MD5是最常見的摘要演算法,速度很快,生成結果是固定的128 bit位元組,通常用一個32位的16進制字串表示,另一種常見的摘要演算法是SHA1,呼叫SHA1和呼叫MD5完全類似:
SHA1的結果是160 bit位元組,通常用一個40位的16進制字串表示,比SHA1更安全的演算法是SHA256和SHA512,不過越安全的演算法越慢,而且摘要長度更長,
2、摘要演算法應用
任何允許用戶登錄的網站都會存盤用戶登錄的用戶名和口令,如何存盤用戶名和口令呢?方法是存到資料庫表中:
name | password
--------+----------
michael | 123456
bob | abc999
alice | alice2008
如果以明文保存用戶口令,如果資料庫泄露,所有用戶的口令就落入黑客的手里,此外,網站運維人員是可以訪問資料庫的,也就是能獲取到所有用戶的口令,正確的保存口令的方式是不存盤用戶的明文口令,而是存盤用戶口令的摘要,比如MD5:
username | password
---------+---------------------------------
michael | e10adc3949ba59abbe56e057f20f883e
bob | 878ef96e86145580c38c87f0410ad153
alice | 99b1c2188db85afee403b1536010c2c9
考慮這么個情況,很多用戶喜歡用123456,888888,password這些簡單的口令,于是,黑客可以事先計算出這些常用口令的MD5值,得到一個反推表:
'e10adc3949ba59abbe56e057f20f883e': '123456'
'21218cca77804d2ba1922c33e0151105': '888888'
'5f4dcc3b5aa765d61d8327deb882cf99': 'password'
這樣,無需破解,只需要對比資料庫的MD5,黑客就獲得了使用常用口令的用戶賬號,
對于用戶來講,當然不要使用過于簡單的口令,但是,我們能否在程式設計上對簡單口令加強保護呢?
由于常用口令的MD5值很容易被計算出來,所以,要確保存盤的用戶口令不是那些已經被計算出來的常用口令的MD5,這一方法通過對原始口令加一個復雜字串來實作,俗稱“加鹽”:
hashlib.md5("salt".encode("utf8"))
經過Salt處理的MD5口令,只要Salt不被黑客知道,即使用戶輸入簡單口令,也很難通過MD5反推明文口令,
但是如果有兩個用戶都使用了相同的簡單口令比如123456,在資料庫中,將存盤兩條相同的MD5值,這說明這兩個用戶的口令是一樣的,有沒有辦法讓使用相同口令的用戶存盤不同的MD5呢?
如果假定用戶無法修改登錄名,就可以通過把登錄名作為Salt的一部分來計算MD5,從而實作相同口令的用戶也存盤不同的MD5,
摘要演算法在很多地方都有廣泛的應用,要注意摘要演算法不是加密演算法,不能用于加密(因為無法通過摘要反推明文),只能用于防篡改,但是它的單向計算特性決定了可以在不存盤明文口令的情況下驗證用戶口令,
''' 注意:把一段很長的資料update多次,與一次update這段長資料,得到的結果一樣 ''' import hashlib m = hashlib.md5() # m=hashlib.sha256() m.update('hello'.encode('utf8')) print(m.hexdigest()) # 5d41402abc4b2a76b9719d911017c592 m.update('world'.encode('utf8')) print(m.hexdigest()) # fc5e038d38a57032085441e7fe7010b0 m2 = hashlib.md5() m2.update('helloworld'.encode('utf8')) print(m2.hexdigest()) # fc5e038d38a57032085441e7fe7010b0 hashlibhashlib
def get_md5_doc(file, size): obj = hashlib.md5('+Yan'.encode('utf8')) # 密碼加鹽 with open(file, 'rb') as f: while size: content = f.read(10) obj.update(content) size -= len(content) return obj.hexdigest()md5對檔案加密
十一、re 模塊
正則運算式是用來---->匹配 字串
字串提供的方法是完全匹配,模糊匹配沒辦法處理,
python 通過import re模塊來實作,呼叫正則運算式的方法,實作模糊匹配
字符匹配(普通字符,元字符):
普通字符:大多數字符和字母都會和自身匹配
元字符:
. 點,占一位,代指所有字符,除了換行符, ^ 尖角號,只從字串開頭 開始匹配, $ dollar符,只從字串結尾 開始匹配, * 星號,把前一個(普通字符、一個或者幾個元字符)重復匹配0到無窮次, + 加號,把前一個(普通字符、一個或者幾個元字符)重復匹配1到無窮次, ? 問號,把前一個(普通字符、一個或者幾個元字符)重復匹配0到1次, {} {3}指定匹配前一個元素重復3次,{1,3}指定匹配前一個元素重復1/2/3次 [] 字符集,[cd]匹配兩者之一,[a-z]匹配26個字母之一,[a*]把元字符變成普通字符 | 管道,符號兩邊取或 () 分組,把正則運算式中需要回傳的值括起來, \ 反斜杠后邊跟元字符是去除特殊功能的,反斜杠后面跟普通字符可以實作特殊功能: \d 匹配任何十進制數;它相當于類[0-9] \D 匹配任何非數字字符;它相當于類[^0-9] \s 匹配任何空白字符;它相當于類[\t\n\r\f\v] \S 匹配任何非空白字符;它相當于類[^\t\n\r\f\v] \w 匹配任何字母數字字符;它相當于類[a-zA-Z0-9_] \W 匹配任何非字母數字字符;它相當于類[^a-zA-Z0-9_] \b 匹配任何一個特殊字符邊界,元字符
re.findall() #匹配到 回傳字串組成的串列,沒有結果回傳空串列, re.search().group() #找到第一個匹配值后就回傳,回傳結果是一個Match object,需要通過.group()提取資料,如果沒有結果,回傳None re.match().group() #同search,不過僅在字串開始處進行匹配, re.split("[ab]","abcd") #先按'a'分隔得到""和"bcd",再對""和"bcd"按照'b'分割 re.sub("\d","abc","alvin5yuan6",1) #第四位引數,指定替換幾個值 re.finditer('\d',"acd3d4f5") #把匹配值放進迭代器re的方法
import re g = re.finditer('\d',"acd3d4f5") # 迭代器 print(next(g).group()) print(next(g).group()) u = re.sub("\d","abc","alvin5yuan6",1) # alvinabcyuan6 print(u) x1 = re.findall("i\\b","i like python") # ['i'] \b 捕捉特殊字符邊界, print(x1) x = re.findall("i\\b","i li$e python") # ['i', 'i'] \b 捕捉特殊字符邊界, print(x) z7 = re.findall("[^ab]","a*ba2ba2*b,a2a*") # ['*', '2', '2', '*', '2', '*'] 尖角號,取消特殊功能后,放在[]里頭是取反的意思 print(z7) z6 = re.findall("a,b","a,ba2ba2,ba2a,") # ['a,b'] 逗號 print(z6) z5 = re.findall("a[2,]b","a,ba2ba2,ba2a,") # ['a,b', 'a2b'] 逗號與2 二取一 print(z5) z4 = re.findall("a[2*]b","a*ba2ba2*ba2a*") # ['a*b', 'a2b'] 星號與2 二取一,取消星號特殊功能 print(z4) z3 = re.findall("a[0-9]b","acbadbasdba2b") # ['a2b'] print(z3) z2 = re.findall("a[a-z]b","acbadbasdba2b") # ['acb', 'adb'] print(z2) z1 = re.findall("a[c,d]b","acbadbasdb") # ['acb', 'adb'] print(z1) s5 = re.findall("a{1,}b","aaaaabaababb") # ['aaaaab', 'aab', 'ab']相當于a+b print(s5) s4 = re.findall("a{0,}b","aaaaabaababb") # ['aaaaab', 'aab', 'ab', 'b'] 相當于a*b print(s4) s3 = re.findall("a{1,3}b","aaaaab") #['aaab'] 默認貪婪匹配 print(s3) s2 = re.findall("a{1,3}b","aaaaabaababb") #['aaab', 'aab', 'ab'] print(s2) s1 = re.findall("a{3}b","aaaaabaababb") #['aaab'] print(s1) ret_6 = re.findall("a.*?b","aaaaabaababb") #['aaaaab', 'aab', 'ab'] print(ret_6) ret_5 = re.findall("a.*b","aaaaabaababb") #['aaaaabaababb'] print(ret_5) ret_4 = re.findall("a*b","aaaaabaababb") #['aaaaab', 'aab', 'ab', 'b'] print(ret_4) ret_3 = re.findall("a+b","aaaaabaababb") # ['aaaaab', 'aab', 'ab'] print(ret_3) ret_3 = re.findall("如.*哈","如哈") print(ret_3) ret_2 = re.findall("a..x$","alexh") # [] $ dollar符要求只從字串結尾開始匹配, print(ret_2) ret_1 = re.findall("^h...0","hjsonhello") # [] ^尖角號要求只從字串開頭開始匹配, print(ret_1) ret = re.findall("w\w{2}l","hello world") print(ret) # ['worl']例子
練習 開發一個簡單的python計算器
1.實作加減乘除及括號優先級決議
2.用戶輸入1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))等類似公式后,必須自己決議里面的(),+
,-,*,/符號和公式(不能呼叫eval()函式實作),然后得出結果,
十一、logging模塊
CRITICAL = 50 #FATAL = CRITICAL ERROR = 40 WARNING = 30 #WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0 #不設定日志級別
默認級別為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引數會被忽略, #格式 %(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:用戶輸出的訊息 logging.basicConfig()basicConfig
#========使用 import logging logging.basicConfig(filename='access.log', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level=10) logging.debug('除錯debug') logging.info('訊息info') logging.warning('警告warn') logging.error('錯誤error') logging.critical('嚴重critical') #========結果 access.log內容: 2017-07-28 20:32:17 PM - root - DEBUG -test: 除錯debug 2017-07-28 20:32:17 PM - root - INFO -test: 訊息info 2017-07-28 20:32:17 PM - root - WARNING -test: 警告warn 2017-07-28 20:32:17 PM - root - ERROR -test: 錯誤error 2017-07-28 20:32:17 PM - root - CRITICAL -test: 嚴重critical初級日志檔案
#logger:產生日志的物件 #Filter:過濾日志的物件 #Handler:接收日志然后控制列印到不同的地方,FileHandler用來列印到檔案中,StreamHandler用來列印到終端 #Formatter物件:可以定制不同的日志格式物件,然后系結給不同的Handler物件使用,以此來控制不同的Handler的日志格式 通過handler 給logger 物件 多個輸出方式,fornatter為 logger 指定輸出格式復雜的日志檔案
import logging from logging import handlers # 生成logger物件 logger = logging.getLogger('web') logger.setLevel(logging.DEBUG) # 生成handler物件 ch = handlers.RotatingFileHandler('test.log',maxBytes=50,backupCount=2) fh = logging.FileHandler('web.log') # 把handler物件系結到logger logger.addHandler(ch) logger.addHandler(fh) # 生成formatter物件 ch_formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s') ch.setLevel(logging.INFO) fh_formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(levelno)s-%(message)s') fh.setLevel(logging.WARNING) # 把formatter物件系結到logger ch.setFormatter(ch_formatter) fh.setFormatter(fh_formatter) logger.debug('debug') logger.info('info') logger.warning('warning') logger.critical('critical') logger.error('error')logging 多個handler
def get_logger(): logger = logging.getLogger('ftp') # 創建一個logger物件 logger.setLevel(logging.INFO) # 設定日志級別 # handler ch = logging.StreamHandler() # 創建一個handler物件 filename = settings.LOGGING_DIR fh = logging.FileHandler(filename) # 創建一個handler物件 # formatter formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(filename)s - %(message)s') # bind formatter to handler ch.setFormatter(formatter) fh.setFormatter(formatter) # add handler to logger logger.addHandler(ch) logger.addHandler(fh) return logger get_logger().info('記錄一下...')輸出到檔案和終端的日志
需要注意的是filter的順序,
logger的 日志級別是第一級過濾,
然后會給handler,
十三、subrocess 模塊
import subprocess def for_shell(self,head_dic): """這個就是處理系統命令,拿到執行結果""" cmd = head_dic['cmd'] obj = subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = obj.stdout.read().decode('GBK'),obj.stderr.read().decode('GBK') res_head_dic = {'res': stderr + stdout} return res_head_dicsubprocess
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/71730.html
標籤:Python
上一篇:Qt 之 Graphics View Framework 簡介
下一篇:Python 函式
