模塊分為三種:
import modulefrom module import xxfrom module.xx.xx import xx as rename from module.xx.xx import *View Code
模塊一旦被調(diào)用,即相當(dāng)于執(zhí)行了另外一個(gè)py文件里的代碼
這個(gè)最簡單, 創(chuàng)建一個(gè).py文件,就可以稱之為模塊,就可以在另外一個(gè)程序里導(dǎo)入
import sysprint(sys.path)['', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages']View Code
python解釋器會(huì)按照列表順序去依次到每個(gè)目錄下去匹配你要導(dǎo)入的模塊名,只要在一個(gè)目錄下匹配到了該模塊名,就立刻導(dǎo)入,不再繼續(xù)往后找。
注意列表第一個(gè)元素為空,即代表當(dāng)前目錄,所以你自己定義的模塊在當(dāng)前目錄會(huì)被優(yōu)先導(dǎo)入。
https://pypi.python.org/pypi?是python的開源模塊庫
1.直接在上面這個(gè)頁面上點(diǎn)download,下載后,解壓并進(jìn)入目錄,執(zhí)行以下命令完成安裝
編譯源碼 python setup.py build安裝源碼 python setup.py installView Code
2.直接通過pip安裝
pip3 install paramiko #paramiko 是模塊名View Code
pip命令會(huì)自動(dòng)下載模塊包并完成安裝。
軟件一般會(huì)被自動(dòng)安裝你python安裝目錄的這個(gè)子目錄里
/your_python_install_path/3.6/lib/python3.6/site-packages
pip命令默認(rèn)會(huì)連接在國外的python官方服務(wù)器下載,速度比較慢,你還可以使用國內(nèi)的豆瓣源,數(shù)據(jù)會(huì)定期同步國外官網(wǎng),速度快好多
sudo pip install -i http://pypi.douban.com/simple/ alex_sayhi --trusted-host pypi.douban.com #alex_sayhi是模塊名
下載后,直接導(dǎo)入使用就可以,跟自帶的模塊調(diào)用方法無差,演示一個(gè)連接linux執(zhí)行命令的模塊
#coding:utf-8import paramikossh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())ssh.connect('192.168.1.108', 22, 'alex', '123')stdin, stdout, stderr = ssh.exec_command('df')print(stdout.read())ssh.close();執(zhí)行命令 - 通過用戶名和密碼連接服務(wù)器View Code
當(dāng)你的模塊文件越來越多,就需要對模塊文件進(jìn)行劃分,比如把負(fù)責(zé)跟數(shù)據(jù)庫交互的都放一個(gè)文件夾,把與頁面交互相關(guān)的放一個(gè)文件夾
.└── my_proj ├── crm #代碼目錄 │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── tests.py │ └── views.py ├── manage.py └── my_proj #配置文件目錄 ├── settings.py ├── urls.py └── wsgi.py
像上面這樣,一個(gè)文件夾管理多個(gè)模塊文件,這個(gè)文件夾就被稱為包,包就是文件夾,但該文件夾下必須存在 __init__.py 文件, 該文件的內(nèi)容可以為空。__int__.py用于標(biāo)識(shí)當(dāng)前文件夾是一個(gè)包。
那不同包之間的模塊互相導(dǎo)入呢?
crm/views.py內(nèi)容
def sayhi(): print('hello world!')View Code
通過manage.py調(diào)用
from crm import viewsviews.sayhi()View Code
import syssys.path.append("C:\\Users\Administrator\PycharmProjects\myFirstpro\chapter4模塊的學(xué)習(xí)\my_proj")#這個(gè)是靜態(tài)路徑,右鍵path它的路徑。注意是找my_proj這個(gè)路徑這樣才能from.. ##如果加了proj這個(gè)路徑,它就會(huì)自動(dòng)往里邊去找,直接import settings就可以了#sys.path.append(r"C:\Users\Administrator\PycharmProjects\myFirstpro\chapter4模塊的學(xué)習(xí)\my_proj") ##加rprint(sys.path)from proj import settingsdef sayhi(): print('Hello World!')View Code
import sys,osprint(dir())print(‘file’,_file_)BASE_DIR = os.path.dirname(os.path.dirname(_file_))print(BASE_DIR)sys.path.append(BASE_DIR) #這個(gè)是動(dòng)態(tài)路徑 from proj import settingsdef sayhi(): print('Hello world!')打?。篬'__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'os', 'sys']C:/Users/Administrator/PycharmProjects/myFirstpro/chapter4模塊的學(xué)習(xí)/my_proj/crm/views.pyC:/Users/Administrator/PycharmProjects/myFirstpro/chapter4模塊的學(xué)習(xí)/my_projin proj/settings.pyView Code
import sys,osprint(dir())print(‘file’,_file_)BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(_file_))) #這是絕對路徑,這樣在哪里執(zhí)行都沒有問題了print(BASE_DIR)sys.path.append(BASE_DIR)from proj import settingsdef sayhi(): print('Hello world!')View Code
在linux里可以通過cd ..回到上一層目錄 ,cd ../.. 往上回2層,這個(gè)..就是指相對路徑,在python里,導(dǎo)入也可以通過..
├── __init__.py├── crm│ ├── __init__.py│ ├── admin.py│ ├── apps.py│ ├── models.py│ ├── tests.py│ ├── views.py ├── manage.py └── proj ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py#from crm import modelsfrom . import models #from crm import models 這兩個(gè)是一樣的 #. 就叫相對導(dǎo)入,因?yàn)樗鼈z在同一級目錄def sayhi(): print('Hello world!')#執(zhí)行manageView Code?
在python里通常有下面幾種表示時(shí)間的方式:
索引(Index) 屬性(Attribute) 值(Values)0 tm_year(年) 比如2011 1 tm_mon(月) 1 - 122 tm_mday(日) 1 - 313 tm_hour(時(shí)) 0 - 234 tm_min(分) 0 - 595 tm_sec(秒) 0 - 616 tm_wday(weekday) 0 - 6(0表示周日)7 tm_yday(一年中的第幾天) 1 - 3668 tm_isdst(是否是夏令時(shí)) 默認(rèn)為-1
time.localtime()將當(dāng)前時(shí)間轉(zhuǎn)為當(dāng)前時(shí)區(qū)的struct_time;wday 0-6表示周日到周六;ydat 1-366 一年中的第幾天;?isdst 是否為夏令時(shí),默認(rèn)為-1;
time.gmtime()
>>>import time>>>time.time() #返回當(dāng)前的時(shí)間戳1507808689.675603>>>time.localtime() #將一個(gè)時(shí)間戳轉(zhuǎn)換為當(dāng)前時(shí)區(qū)的struct_timetime.struct_time( tm_year=2017, tm_mon=10, tm_mday=12, tm_hour=19, tm_min=45, tm_sec=61, tm_wday=3, tm_yday=285, tm_isdst=0) #打印本地時(shí)間>>>time.gmtime() #將一個(gè)時(shí)間戳轉(zhuǎn)換為UTC標(biāo)準(zhǔn)時(shí)間,比我們晚8個(gè)小時(shí)time.struct_time( tm_year=2017, tm_mon=10, tm_mday=12, tm_hour=11, tm_min=47, tm_sec=51, tm_wday=3, tm_yday=285, tm_isdst=0)View Code
>>>a = time.localtime(1403232424) >>>atime.struct_time( tm_year=2014, tm_mon=6, tm_mday=20, tm_hour=10, tm_min=47, tm_sec=4, tm_wday=4, tm_yday=171, tm_isdst=0)View Code
字符串的拼接 、 time.mktime()
>>>'%s-%s-%s'%(a.tm_year, a.tm_mon, a.tm_mday) #可以進(jìn)行拼接‘2017-10-12’>>>time.mktime(a) #將一個(gè)struct_time轉(zhuǎn)化為時(shí)間戳。140323242.0View Code
time.asctime() ?(外國人常使用的時(shí)間形式) ?、time.ctime()將當(dāng)前時(shí)間轉(zhuǎn)換為一個(gè)字符串str
>>>time.asctime() #把一個(gè)表示時(shí)間的元組或者struct_time表示為這種形式:'Sun Oct 1 12:04:38 2017'。'Thu Oct 12 19:52:10 2017'>>>time.ctime() #把一個(gè)時(shí)間戳(按秒計(jì)算的浮點(diǎn)數(shù))轉(zhuǎn)化為time.asctime()的形式。相當(dāng)于time.asctime(time.localtime(secs))'Thu Oct 12 19:52:36 2017'>>>time.ctime(123232)'Fri Jan 2 18:13:52 1970'>>>time.ctime(0)'Thu Jan 1 08:00:00 1970'View Code
time.sleep(secs):線程推遲指定的時(shí)間運(yùn)行。單位為秒。
time.strftime( ‘%Y-%m-%d ?%H:%M:%S ?%A %P %U’ )?轉(zhuǎn)化為格式化的字符串 ? ? ? ? time.strptime(s, ?‘%Y-%m-%d ?%H:%M:%S ’ ) ?把格式化字符串進(jìn)行反轉(zhuǎn)為struct_time
time.strftime(a,b)??,?a為格式化字符串格式 ?,?b為時(shí)間戳,一般用localtime()
>>>atime.struct_time(tm_year=1974, tm_mon=6, tm_day=13, tm_hour=10, tm_min=40, tm_sec=42, tm_wday=3, tm_yday=164, tm_isdst=0)>>>time.strftime('%Y-%m-%d %H:%M:%S',a) #把一個(gè)代表時(shí)間的元組或者struct_time(如由time.localtime()和time.gmtime()返回)轉(zhuǎn)化為格式化的時(shí)間字符串'1974-06-13 10:40:42'>>>time.strftime('%Y-%m-%d %H:%M:%S',) #不加就默認(rèn)當(dāng)前時(shí)間'2017-10-12 19:56:31'>>>time.strftime('%Y-%m-%d %H:%M:%S %A',a) # %A 星期幾'1974-06-13 10:40:42 Thursday'>>>time.strftime('%Y-%m-%d %H:%M:%S %p',a) #%p AM or PM'1974-06-13 10:40:42 AM'>>>time.strftime('%Y-%m-%d %H:%M:%S %U',a) #%U一年的第幾周'1974-06-13 10:40:42 23'>>> import time>>> print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))2018-07-28 14:12:17View Code
>>>s=time.strftime('%Y-%m-%d %H:%M:%S')>>>s'2017 10-12 20:00:56'time.strptime(s, '%Y %m-%d %H:%M:%S') #反轉(zhuǎn) #把一個(gè)格式化時(shí)間字符串轉(zhuǎn)化為struct_timetime.struct_time(tm_year=2017, tm_mon=,10, tm_day=12, tm_hour=20, tm_min=1, tm_sec=26, tm_wday=3, tm_yday=285, tm_isdst=-1)>>>time.mktime(s) #把時(shí)間對象又變成時(shí)間戳1507809686.0View Code
datatime模塊
datetime.datetime.now()?返回當(dāng)前的datetime日期類型,d.timestamp(),d.today(), d.year,d.timetuple()等方法可以調(diào)用
>>>import datetime>>>datetime.datetime.now() #a.timestamp(),a.today(), a.year,a.timetuple()等方法可以調(diào)用;打印出下面的時(shí)間datetime.datetime(2017, 10, 12, 20, 8, 19, 393189)View Code
datetime.date.fromtimestamp() ?#把時(shí)間戳轉(zhuǎn)化為datetime類型
>>>d2= datetime.date.fromtimestamp(time.time()) #快速的把時(shí)間戳拿到它的年月日>>>d2datetime.date(2017, 10, 12)>>>d2.timetuple()time.struct_time(tm_year=2017, tm_mon=10, tm_mday=12, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=285, tm_isdst=-1) #其中三個(gè)為0,顯示不了View Code
重點(diǎn)是進(jìn)行時(shí)間的運(yùn)算 ?
datetime.datetime.now() (-) datetime.timedelta()
>>>t = datetime.timedelta(1)>>>datetime.datetime.now() - tdatetime.datetime(2017, 10, 11, 20, 12, 37, 106915)>>>datetime.datetime.now() - datetime.timedelta(days=1)datetime.datetime(2017, 10, 11, 20, 12, 37, 106915)>>>datetime.datetime.now() - datetime.timedelta(hours=3)datetime.datetime(2017, 10, 12, 17, 13, 14, 617201)>>>datetime.datetime.now() datetime.timedelta(minutes=10)datetime.datetime(2017, 10, 12, 20, 24, 2, 178282)>>>datetime.datetime.now() datetime.timedelta(seconds=10)datetime.datetime(2017, 10, 12, 20, 14, 23, 858086)View Code
時(shí)間的替換
>>>d.replace()datetime.datetime(2017, 10, 12, 20, 15, 17,457249)>>>d.replace(year=2016)datetime.datetime(2016, 10, 12, 20, 15, 17,457249)>>>d.replace(year=2016,month=8)datetime.datetime(2016, 8, 12, 20, 15, 17,457249)View Code
>>> random.randrange(1,10) #返回1-10之間的一個(gè)隨機(jī)數(shù),不包括10>>> random.randint(1,10) #返回1-10之間的一個(gè)隨機(jī)數(shù),包括10>>> random.randrange(0, 100, 2) #隨機(jī)選取0到100間的偶數(shù)>>> random.random() #返回一個(gè)隨機(jī)浮點(diǎn)數(shù)>>> random.choice('abce3#$@1') #返回一個(gè)給定數(shù)據(jù)集合中的隨機(jī)字符'#'>>> random.sample('abcdefghij',3) #從多個(gè)字符中選取特定數(shù)量的字符['a', 'd', 'b']#生成隨機(jī)字符串>>> import string >>> ''.join(random.sample(string.ascii_lowercase string.digits, 6)) '4fvda1'#洗牌>>> a[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>> random.shuffle(a)>>> a[3, 0, 7, 2, 1, 6, 5, 8, 9, 4]View Code
os 模塊提供了很多允許你的程序與操作系統(tǒng)直接交互的功能
得到當(dāng)前工作目錄,即當(dāng)前Python腳本工作的目錄路徑: os.getcwd()返回指定目錄下的所有文件和目錄名:os.listdir()函數(shù)用來刪除一個(gè)文件:os.remove()刪除多個(gè)目錄:os.removedirs(r“c:\python”)檢驗(yàn)給出的路徑是否是一個(gè)文件:os.path.isfile()檢驗(yàn)給出的路徑是否是一個(gè)目錄:os.path.isdir()判斷是否是絕對路徑:os.path.isabs()檢驗(yàn)給出的路徑是否真地存:os.path.exists()返回一個(gè)路徑的目錄名和文件名:os.path.split() e.g os.path.split('/home/swaroop/byte/code/poem.txt') 結(jié)果:('/home/swaroop/byte/code', 'poem.txt') 分離擴(kuò)展名:os.path.splitext() e.g os.path.splitext('/usr/local/test.py') 結(jié)果:('/usr/local/test', '.py')獲取路徑名:os.path.dirname()獲得絕對路徑: os.path.abspath() 獲取文件名:os.path.basename()運(yùn)行shell命令: os.system()讀取操作系統(tǒng)環(huán)境變量HOME的值:os.getenv("HOME") 返回操作系統(tǒng)所有的環(huán)境變量: os.environ 設(shè)置系統(tǒng)環(huán)境變量,僅程序運(yùn)行時(shí)有效:os.environ.setdefault('HOME','/home/alex')給出當(dāng)前平臺(tái)使用的行終止符:os.linesep Windows使用'\r\n',Linux and MAC使用'\n'指示你正在使用的平臺(tái):os.name 對于Windows,它是'nt',而對于Linux/Unix用戶,它是'posix'重命名:os.rename(old, new)創(chuàng)建多級目錄:os.makedirs(r“c:\python\test”)創(chuàng)建單個(gè)目錄:os.mkdir(“test”)獲取文件屬性:os.stat(file)修改文件權(quán)限與時(shí)間戳:os.chmod(file)獲取文件大?。簅s.path.getsize(filename)結(jié)合目錄名與文件名:os.path.join(dir,filename)改變工作目錄到dirname: os.chdir(dirname)獲取當(dāng)前終端的大小: os.get_terminal_size()殺死進(jìn)程: os.kill(10884,signal.SIGKILL)View Code
sys.argv 命令行參數(shù)List,第一個(gè)元素是程序本身路徑sys.exit(n) 退出程序,正常退出時(shí)exit(0)sys.version 獲取Python解釋程序的版本信息sys.maxint 最大的Int值sys.path 返回模塊的搜索路徑,初始化時(shí)使用PYTHONPATH環(huán)境變量的值sys.platform 返回操作系統(tǒng)平臺(tái)名稱sys.stdout.write('please:') #標(biāo)準(zhǔn)輸出 , 引出進(jìn)度條的例子, 注,在py3上不行,可以用print代替val = sys.stdin.readline()[:-1] #標(biāo)準(zhǔn)輸入sys.getrecursionlimit() #獲取最大遞歸層數(shù)sys.setrecursionlimit(1200) #設(shè)置最大遞歸層數(shù)sys.getdefaultencoding() #獲取解釋器默認(rèn)編碼sys.getfilesystemencoding #獲取內(nèi)存數(shù)據(jù)存到文件里的默認(rèn)編碼View Code
高級的 文件、文件夾、壓縮包 處理模塊
shutil.copyfileobj(fsrc, fdst[, length])
將文件內(nèi)容拷貝到另一個(gè)文件中
import shutilshutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))View Code
shutil.copyfile(src, dst)
拷貝文件
shutil.copyfile('f1.log', 'f2.log') #目標(biāo)文件無需存在View Code
shutil.copymode(src, dst)
僅拷貝權(quán)限。內(nèi)容、組、用戶均不變
shutil.copymode('f1.log', 'f2.log') #目標(biāo)文件必須存在View Code
shutil.copystat(src, dst)
僅拷貝狀態(tài)的信息,包括:mode bits, atime, mtime, flags
shutil.copystat('f1.log', 'f2.log') #目標(biāo)文件必須存在View Code
shutil.copy(src, dst)
拷貝文件和權(quán)限
import shutilshutil.copy('f1.log', 'f2.log')View Code
shutil.copy2(src, dst)
拷貝文件和狀態(tài)信息
import shutilshutil.copy2('f1.log', 'f2.log')View Code
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
遞歸的去拷貝文件夾
import shutilshutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目標(biāo)目錄不能存在,注意對folder2目錄父級目錄要有可寫權(quán)限,ignore的意思是排除View Code
shutil.rmtree(path[, ignore_errors[, onerror]])
遞歸的去刪除文件
import shutilshutil.rmtree('folder1')View Code
shutil.move(src, dst)
遞歸的去移動(dòng)文件,它類似mv命令,其實(shí)就是重命名。
import shutilshutil.move('folder1', 'folder3')View Code
shutil.make_archive(base_name, format,...)
創(chuàng)建壓縮包并返回文件路徑,例如:zip、tar
創(chuàng)建壓縮包并返回文件路徑,例如:zip、tar
如 data_bak =>保存至當(dāng)前路徑
如:/tmp/data_bak =>保存至/tmp/
#將 /data 下的文件打包放置當(dāng)前程序目錄import shutilret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')#將 /data下的文件打包放置 /tmp/目錄import shutilret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')View Code
shutil 對壓縮包的處理是調(diào)用 ZipFile 和 TarFile 兩個(gè)模塊來進(jìn)行的,詳細(xì):
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()View Code
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()View Code
序列化是指把內(nèi)存里的數(shù)據(jù)類型轉(zhuǎn)變成字符串,以使其能存儲(chǔ)到硬盤或通過網(wǎng)絡(luò)傳輸?shù)竭h(yuǎn)程,因?yàn)橛脖P或網(wǎng)絡(luò)傳輸時(shí)只能接受bytes
用于序列化的兩個(gè)模塊
?
JSON:
優(yōu)點(diǎn):跨語言、體積小
缺點(diǎn):只能支持int\str\list\tuple\dict
Pickle:
優(yōu)點(diǎn):專為python設(shè)計(jì),支持python所有的數(shù)據(jù)類型
缺點(diǎn):只能在python中使用,存儲(chǔ)數(shù)據(jù)占空間大
?
Json模塊提供了四個(gè)功能:dumps、dump、loads、load
pickle模塊提供了四個(gè)功能:dumps、dump、loads、load
import pickledata = {'k1':123,'k2':'Hello'}# pickle.dumps 將數(shù)據(jù)通過特殊的形式轉(zhuǎn)換位只有python語言認(rèn)識(shí)的字符串p_str = pickle.dumps(data)print(p_str)#pickle.dump 將數(shù)據(jù)通過特殊的形式轉(zhuǎn)換位只有python語言認(rèn)識(shí)的字符串,并寫入文件with open('D:/result.pk','wb',encoding='utf8') as fp: pickle.dump(data,fp)import json# json.dumps 將數(shù)據(jù)通過特殊的形式轉(zhuǎn)換位所有程序語言都認(rèn)識(shí)的字符串j_str = json.dumps(data)print(j_str)#pickle.dump 將數(shù)據(jù)通過特殊的形式轉(zhuǎn)換位只有python語言認(rèn)識(shí)的字符串,并寫入文件with open('D:/result.json','wb',encoding='utf8') as fp: json.dump(data,fp)View Code
#序列化data = { 'roles' : [ {'role':'monster','type':'pig','life':50}, {'role':'hero','type':'關(guān)羽','life':80}, ]}f = open('game_status','w')f.write(str(data)) #str把字典轉(zhuǎn)換成字符串View Code
#反序列 把字符轉(zhuǎn)成內(nèi)存數(shù)據(jù)類型data = { 'roles' : [ {'role':'monster','type':'pig','life':50}, {'role':'hero','type':'關(guān)羽','life':80}, ]}# f = open('game_status','w')# f.write(str(data))f = open('game_status','r')d = f.read()d = eval(d) #字符串轉(zhuǎn)成字典print(d['roles'])View Code
import jsondata = { 'roles' : [ {'role':'monster','type':'pig','life':50}, {'role':'hero','type':'關(guān)羽','life':80}, ]}d = json.dumps(data) #僅換成字符串print(d,type(d)) #strd2 = json.loads(d) #把字符串轉(zhuǎn)成相應(yīng)的數(shù)據(jù)類型print(d2,type(d2)) #dictprint(d2['roles'])View Code
打?。簕"roles": [{"role": "monster", "type": "pig", "life": 50}, {"role": "hero", "type": "\u5173\u7fbd", "life": 80}]} <class 'str'>{'roles': [{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '關(guān)羽', 'life': 80}]} <class 'dict'>[{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '關(guān)羽', 'life': 80}]View Code
注意loads和load、 dumps和dump的用法和區(qū)別:
dumps是將dict轉(zhuǎn)化成str格式,loads是將str轉(zhuǎn)化成dict格式。dump和load也是類似的功能,只是與文件操作結(jié)合起來了。
import jsondata = { 'roles' : [ {'role':'monster','type':'pig','life':50}, {'role':'hero','type':'關(guān)羽','life':80}, ]}f = open("test.json", "w")json.dump(data, f) #轉(zhuǎn)成字符串并寫入文件f = open("test.json","r")data = json.load(f) #print(data['roles'])View Code
自動(dòng)生成一個(gè)test.json文件夾{"roles": [{"role": "monster", "type": "pig", "life": 50}, {"role": "hero", "type": "\u5173\u7fbd", "life": 80}]}打印出:[{'role': 'monster', 'type': 'pig', 'life': 50}, {'role': 'hero', 'type': '關(guān)羽', 'life': 80}]View Code
只把數(shù)據(jù)類型轉(zhuǎn)換成字符串存到內(nèi)存里的意義? ?json.dumps ? json.loads
1.把你的內(nèi)存數(shù)據(jù),通過網(wǎng)絡(luò),共享給遠(yuǎn)程其他人;
2.定義了不同語言的之前的交互規(guī)則。
1.純文本, 壞處, 不能共享復(fù)雜的數(shù)據(jù)類型;
2.xml, 壞處 , 占空間大;3.json, 簡單, 可讀性好。
import jsonf = open('json_file', 'w', encoding='utf-8')d = {'name':'alex', 'age':'23'} #字典l = [1,2,3,5,9,'rain'] #列表json.dump(d,f) #可以dump多次json.dump(l,f)自動(dòng)創(chuàng)建json_file的文件:{"name": "alex", "age": "23"}[1, 2, 3, 5, 9, "rain"]View Code
import jsonf = open("json_file", 'r', encoding"utf-8")print(json.load(f)) #反序列化不能load多次,不要dump多次,load多次。只一次,為了避免問題。 json_load文件里邊字典和列表都在里邊不能load,會(huì)報(bào)錯(cuò)。View Code
import pickled = {'name' : 'alex' , 'age' : 22 }l = [1,2,3,4,'rain' ]pk = open("data.pkl", "w")print(pickle.dumps(d)) ##打印bytes類型 b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00alexq\x02X\x03\x00\x00\x00ageq\x03K\x16u.'View Code
import pickled = {'name' : 'alex' , 'age' : 22 }l = [1,2,3,4,'rain' ]pk = open("data.pkl", "wb")print(pickle.dump(d,pk)) #二進(jìn)制的bytes類型的文本格式,存到了硬盤上。print(pickle.dump(l,pk) 自動(dòng)創(chuàng)建data.pkl文件夾:?}q (X nameq X alexq X ageq K u. ?]q (K K K K X rainq e.View Code
從硬盤上讀取數(shù)據(jù)
import picklef = open("data.pkl", "rb")d = pickle.load(f)print(d) #{'name': 'alex', 'age': 22}l = pickle.load(f)print(l) #[1, 2, 3, 4, 'rain']View Code
shelve模塊是一個(gè)簡單的k,v將內(nèi)存數(shù)據(jù)通過文件持久化的模塊,可以持久化任何pickle可支持的python數(shù)據(jù)格式
#序列化import shelvef = shelve.open('shelve_test') # 打開一個(gè)文件names = ["alex", "rain", "test"]info = {'name':'alex','age':22}f["names"] = names # 持久化列表f['info_dic'] = info #持久化dictf.close()#反序列化import shelved = shelve.open('shelve_test') # 打開一個(gè)文件print(d['names']) #['alex', 'rain', 'test']print(d['info_dic']) #{'name': 'alex', 'age': 22}#del d['test'] #還可以刪除View Code
>>>f = shelve.open("shelve_test")>>>f<shelve.DbfilenameShelf object at 0x101dce9e8>>>>list(f.keys())['name', 'info_dic']>>>list(f.items())[('name', ['alex', 'rain', 'test']), ('info_dic', {'name': 'alex', 'age':22})]>>>f.get('names')['alex', 'rain', 'text']>>>f.get('info_dic'){'name': 'alex', 'age':22}>>>f['names'][1]'rain'>>>f['names'][1] = "Rain wang" #不能這樣修改,修改不了,要直接賦值。>>>f['names'][1]None>>>f.close()>>>f = shelve.open("shelve_test")View Code
import shelvef = shelve.open("shelve_test")f['scores'] = [1,2,3,4,5,6]print(f.get('scores'))f['scores'] = [1,2,3,'A',4,'B']print(f.get('scores'))View Code
xml是實(shí)現(xiàn)不同語言或程序之間進(jìn)行數(shù)據(jù)交換的協(xié)議,跟json差不多,但json使用起來更簡單,不過,古時(shí)候,在json還沒誕生的黑暗年代,大家只能選擇用xml呀,至今很多傳統(tǒng)公司如金融行業(yè)的很多系統(tǒng)的接口還主要是xml。
xml的格式如下,就是通過<>節(jié)點(diǎn)來區(qū)別數(shù)據(jù)結(jié)構(gòu)的:
<?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>View Code
import xml.etree.ElementTree as ETtree = ET.parse("xmltest.xml") #openroot = tree.getroot() #f.seek(0)print(root.tag)#遍歷xml文檔for child in root: print('-------------',child.tag,child.attrib) #print(child.tag, child.attrib) for i in child: print(i.tag,i.text)打印:data------------- country {'name': 'Liechtenstein'}rank 2year 2008gdppc 141100neighbor Noneneighbor None------------- country {'name': 'Singapore'}rank 5year 2011gdppc 59900neighbor None------------- country {'name': 'Panama'}rank 69year 2011gdppc 13600neighbor Noneneighbor NoneView Code
import xml.etree.ElementTree as ETtree = ET.parse("xmltest.xml") #openroot = tree.getroot() #f.seek(0)print(root.tag)#只遍歷year 節(jié)點(diǎn)for node in root.iter('year'): print(node.tag,node.text)打?。篸atayear 2008year 2011year 2011View Code
###################自己創(chuàng)建xml文檔#############################import xml.etree.ElementTree as ETnew_xml = ET.Element("namelist") #rootname = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})age = ET.SubElement(name,"age",attrib={"checked":"no"})sex = ET.SubElement(name,"sex")n = ET.SubElement(name,"name")n = "alex"sex.text = 'man'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) #打印生成的格式打?。?lt;?xml version='1.0' encoding='utf-8'?><namelist> <name enrolled="yes"> <age checked="no" /> <sex>man</sex></name> <name enrolled="no"> <age>19</age> </name></namelist>View Code
此模塊用于生成和修改常見配置文檔,當(dāng)前模塊的名稱在 python 3.x 版本中變更為 configparser。
?好多軟件的常見配置文件格式如下:
##conf.ini文件[DEFAULT]ServerAliveInterval = 45Compression = yesCompressionLevel = 9ForwardX11 = yes[bitbucket.org]User = hg[topsecret.server.com]Port = 50022ForwardX11 = noView Code
>>> import configparser>>> config = configparser.ConfigParser() #實(shí)例化生成一個(gè)對象>>> config.sections() #調(diào)用sections方法;在cmd里邊演示[]>>> config.read('example.ini')['example.ini']>>> config.sections() #調(diào)用sections方法(默認(rèn)不會(huì)讀取default方法)['bitbucket.org', 'topsecret.server.com']>>> 'bitbucket.org' in config #判斷元素是否在sections列表內(nèi)True>>> 'bytebong.com' in configFalse>>> config['bitbucket.org']['User'] #通過字典的形式取值'hg'>>> config['DEFAULT']['Compression']'yes'>>> topsecret = config['topsecret.server.com']>>> topsecret['ForwardX11']'no'>>> topsecret['Port']'50022'>>> for key in config['bitbucket.org']: print(key) #for循環(huán)bitbucket.org 字典的key...usercompressionlevelserveraliveintervalcompressionforwardx11>>> config['bitbucket.org']['ForwardX11']'yes'View Code
import configparserconf = configparser.ConfigParser() #先生成一個(gè)對象#print(conf.sections()) #[]conf.read('conf.ini')print(conf.sections())#['bitbucket.org', 'topsecret.server.com']print(conf.default_section) #DEFAULT# print(list(conf["bitbucket.org"].keys()))print(conf["bitbucket.org"]['User']) #hgView Code
#循環(huán)import configparserconf = configparser.ConfigParser() #先生成一個(gè)對象conf.read('conf.ini')for k,v in conf["bitbucket.org"].items(): print(k,v)#打?。簎ser hgserveraliveinterval 45compression yescompressionlevel 9forwardx11 yesView Code
import configparserconf = configparser.ConfigParser() conf.read('conf.ini')if 'user' in conf["bitbucket.org"]: #判斷是否在 print('in')View Code
import configparserconf = configparser.ConfigParser() #先生成一個(gè)對象conf.read("conf_text.ini")conf.add_section("group3")conf["group3"]['name'] = "alex"conf["group3"]['age'] = '22'conf.write(open('conf_test_mew.ini','w')) ###改寫View Code
import configparserconf = configparser.ConfigParser() #先生成一個(gè)對象conf.read("conf_text.ini")#conf.remove_option("group1",'k2')conf.remove_section("group1")conf.write(open('conf_test2_mew.ini','w'))#刪完之后要保存View Code
Hash,一般翻譯做“散列”,也有直接音譯為”哈希”的,就是把任意長度的輸入(又叫做預(yù)映射,pre-image),通過散列算法,變換成固定長度的輸出,該輸出就是散列值。這種轉(zhuǎn)換是一種壓縮映射,也就是,散列值的空間通常遠(yuǎn)小于輸入的空間,不同的輸入可能會(huì)散列成相同的輸出,而不可能從散列值來唯一的確定輸入值。
簡單的說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)。
HASH主要用于信息安全領(lǐng)域中加密算法,他把一些不同長度的信息轉(zhuǎn)化成雜亂的128位的編碼里,叫做HASH值.也可以說,hash就是找到一種數(shù)據(jù)內(nèi)容和數(shù)據(jù)存放地址之間的映射關(guān)系
什么是MD5算法
MD5訊息摘要演算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼雜湊函數(shù),可以產(chǎn)生出一個(gè)128位的散列值(hash value),用于確保信息傳輸完整一致。MD5的前身有MD2、MD3和MD4。
MD5功能
輸入任意長度的信息,經(jīng)過處理,輸出為128位的信息(數(shù)字指紋);
不同的輸入得到的不同的結(jié)果(唯一性);
MD5算法的特點(diǎn)
MD5算法是否可逆?
MD5不可逆的原因是其是一種散列函數(shù),使用的是hash算法,在計(jì)算過程中原文的部分信息是丟失了的。
MD5用途
防止被篡改:
比如發(fā)送一個(gè)電子文檔,發(fā)送前,我先得到MD5的輸出結(jié)果a。然后在對方收到電子文檔后,對方也得到一個(gè)MD5的輸出結(jié)果b。如果a與b一樣就代表中途未被篡改。
比如我提供文件下載,為了防止不法分子在安裝程序中添加木馬,我可以在網(wǎng)站上公布由安裝文件得到的MD5輸出結(jié)果。
SVN在檢測文件是否在CheckOut后被修改過,也是用到了MD5.
防止直接看到明文:
防止抵賴(數(shù)字簽名):
安全哈希算法(Secure Hash Algorithm)主要適用于數(shù)字簽名標(biāo)準(zhǔn)(Digital Signature Standard DSS)里面定義的數(shù)字簽名算法(Digital Signature Algorithm DSA)。對于長度小于2^64位的消息,SHA1會(huì)產(chǎn)生一個(gè)160位的消息摘要。當(dāng)接收到消息的時(shí)候,這個(gè)消息摘要可以用來驗(yàn)證數(shù)據(jù)的完整性。
SHA是美國國家安全局設(shè)計(jì)的,由美國國家標(biāo)準(zhǔn)和技術(shù)研究院發(fā)布的一系列密碼散列函數(shù)。
由于MD5和SHA-1于2005年被山東大學(xué)的教授王小云破解了,科學(xué)家們又推出了SHA224, SHA256, SHA384, SHA512,當(dāng)然位數(shù)越長,破解難度越大,但同時(shí)生成加密的消息摘要所耗時(shí)間也更長。目前最流行的是加密算法是SHA-256 .
由于MD5與SHA-1均是從MD4發(fā)展而來,它們的結(jié)構(gòu)和強(qiáng)度等特性有很多相似之處,SHA-1與MD5的最大區(qū)別在于其摘要比MD5摘要長32 比特。對于強(qiáng)行攻擊,產(chǎn)生任何一個(gè)報(bào)文使之摘要等于給定報(bào)文摘要的難度:MD5是2128數(shù)量級的操作,SHA-1是2160數(shù)量級的操作。產(chǎn)生具有相同摘要的兩個(gè)報(bào)文的難度:MD5是264是數(shù)量級的操作,SHA-1 是280數(shù)量級的操作。因而,SHA-1對強(qiáng)行攻擊的強(qiáng)度更大。但由于SHA-1的循環(huán)步驟比MD5多80:64且要處理的緩存大160比特:128比特,SHA-1的運(yùn)行速度比MD5慢。
用于加密相關(guān)的操作,3.x里代替了md5模塊和sha模塊,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
import hashlibm = hashlib.md5()m.update(b"Hello")m.update(b"It's me")print(m.digest())m.update(b"It's been a long time since last time we ...")print(m.digest()) #2進(jìn)制格式hashprint(len(m.hexdigest())) #16進(jìn)制格式hash'''def digest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of binary data. """ passdef hexdigest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of hexadecimal digits. """ pass'''import hashlib# ######## md5 ########hash = hashlib.md5()hash.update('admin')print(hash.hexdigest())# ######## sha1 ########hash = hashlib.sha1()hash.update('admin')print(hash.hexdigest())# ######## sha256 ########hash = hashlib.sha256()hash.update('admin')print(hash.hexdigest())# ######## sha384 ########hash = hashlib.sha384()hash.update('admin')print(hash.hexdigest())# ######## sha512 ########hash = hashlib.sha512()hash.update('admin')print(hash.hexdigest())View Code
hashlib md5值的用法
#加入下面這個(gè)就可以password = input('請輸入密碼:') m = hashlib.md5() m.update(password.encode()) if m.hexdigest() == data1['password']: print('登錄成功')View Code
我們經(jīng)常需要通過Python去執(zhí)行一條系統(tǒng)命令或腳本,系統(tǒng)的shell命令是獨(dú)立于你的python進(jìn)程之外的,每執(zhí)行一條命令,就是發(fā)起一個(gè)新進(jìn)程,通過python調(diào)用系統(tǒng)命令或腳本的模塊在python2有os.system,
>>> os.system('uname -a')Darwin Alexs-MacBook-Pro.local 15.6.0 Darwin Kernel Version 15.6.0: Sun Jun 4 21:43:07 PDT 2017; root:xnu-3248.70.3~1/RELEASE_X86_64 x86_640
三種執(zhí)行命令的方法
subprocess.run(*popenargs, input=None, timeout=None, check=False, **kwargs) #官方推薦
subprocess.call(*popenargs, timeout=None, **kwargs) #跟上面實(shí)現(xiàn)的內(nèi)容差不多,另一種寫法
subprocess.Popen() #上面各種方法的底層封裝
run方法
#標(biāo)準(zhǔn)寫法subprocess.run(['df','-h'],stderr=subprocess.PIPE,stdout=subprocess.PIPE,check=True)#涉及到管道|的命令需要這樣寫subprocess.run('df -h|grep disk1',shell=True) #shell=True的意思是這條命令直接交給系統(tǒng)去執(zhí)行,不需要python負(fù)責(zé)解析View Code
#執(zhí)行命令,返回命令執(zhí)行狀態(tài) , 0 or 非0>>> retcode = subprocess.call(["ls", "-l"])#執(zhí)行命令,如果命令結(jié)果為0,就正常返回,否則拋異常>>> subprocess.check_call(["ls", "-l"])#接收字符串格式命令,返回元組形式,第1個(gè)元素是執(zhí)行狀態(tài),第2個(gè)是命令結(jié)果 >>> subprocess.getstatusoutput('ls /bin/ls')(0, '/bin/ls')#接收字符串格式命令,并返回結(jié)果>>> subprocess.getoutput('ls /bin/ls')'/bin/ls'#執(zhí)行命令,并返回結(jié)果,注意是返回結(jié)果,不是打印,下例結(jié)果返回給res>>> res=subprocess.check_output(['ls','-l'])>>> resb'total 0\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\n'View Code
常用參數(shù):
a=subprocess.run('sleep 10',shell=True,stdout=subprocess.PIPE)a=subprocess.Popen('sleep 10',shell=True,stdout=subprocess.PIPE)
區(qū)別是Popen會(huì)在發(fā)起命令后立刻返回,而不等命令執(zhí)行結(jié)果。這樣的好處是什么呢?
如果你調(diào)用的命令或腳本 需要執(zhí)行10分鐘,你的主程序不需卡在這里等10分鐘,可以繼續(xù)往下走,干別的事情,每過一會(huì),通過一個(gè)什么方法來檢測一下命令是否執(zhí)行完成就好了。
Popen調(diào)用后會(huì)返回一個(gè)對象,可以通過這個(gè)對象拿到命令執(zhí)行結(jié)果或狀態(tài)等,該對象有以下方法
poll()
Check if child process has terminated. Returns returncode
wait()
Wait for child process to terminate. Returns returncode attribute.
terminate()
終止所啟動(dòng)的進(jìn)程Terminate the process with SIGTERM
kill()
?殺死所啟動(dòng)的進(jìn)程 Kill the process with SIGKILL
communicate()
與啟動(dòng)的進(jìn)程交互,發(fā)送數(shù)據(jù)到stdin,并從stdout接收輸出,然后等待任務(wù)結(jié)束
>>> a = subprocess.Popen('python3 guess_age.py',stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE,shell=True)>>> a.communicate(b'22')(b'your guess:try bigger\n', b'')
send_signal(signal.xxx)
發(fā)送系統(tǒng)信號
pid
?拿到所啟動(dòng)進(jìn)程的進(jìn)程號
logging模塊
很多程序都有記錄日志的需求,并且日志中包含的信息即有正常的程序訪問日志,還可能有錯(cuò)誤、警告等信息輸出,python的logging模塊提供了標(biāo)準(zhǔn)的日志接口,你可以通過它存儲(chǔ)各種格式的日志,logging的日志可以分為?debug(), info(), warning(), error() and critical()
5個(gè)級別,下面我們看一下怎么用。
#最簡單用法import logginglogging.warning("user [alex] attempted wrong password more than 3 times")logging.critical("server is down")View Code
#輸出WARNING:root:user [alex] attempted wrong password more than 3 timesCRITICAL:root:server is downView Code
import logginglogging.basicConfig(filename='example.log',level=logging.INFO)logging.debug('This message should go to the log file')logging.info('So should this')logging.warning('And this, too')View Code
其中下面這句中的level=loggin.INFO意思是,把日志紀(jì)錄級別設(shè)置為INFO,也就是說,只有比日志是INFO或比INFO級別更高的日志才會(huì)被紀(jì)錄文件里,在這個(gè)例子, 第一條日志是不會(huì)被紀(jì)錄的,如果希望紀(jì)錄debug的日志,那把日志級別改成DEBUG就行了.
?
?
感覺上面的日志格式忘記加上時(shí)間啦,日志不知道時(shí)間怎么行呢,下面就來加上!
import logginglogging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')logging.warning('is when this event was logged.')#輸出12/12/2010 11:46:36 AM is when this event was logged.View Code
如果想同時(shí)把log打印在屏幕和文件日志里,就需要了解一點(diǎn)復(fù)雜的知識(shí) 了
Python 使用logging模塊記錄日志涉及四個(gè)主要類,使用官方文檔中的概括最為合適:
?
每個(gè)程序在輸出信息之前都要獲得一個(gè)Logger。Logger通常對應(yīng)了程序的模塊名,比如聊天工具的圖形界面模塊可以這樣獲得它的Logger:
LOG=logging.getLogger(”chat.gui”)
而核心模塊可以這樣:
LOG=logging.getLogger(”chat.kernel”)
還可以綁定handler和filters
Logger.setLevel(lel):指定最低的日志級別,低于lel的級別將被忽略。debug是最低的內(nèi)置級別,critical為最高Logger.addFilter(filt)、Logger.removeFilter(filt):添加或刪除指定的filterLogger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或刪除指定的handler
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以設(shè)置的日志級別
handler對象負(fù)責(zé)發(fā)送相關(guān)的信息到指定目的地。Python的日志系統(tǒng)有多種Handler可以使用。有些Handler可以把信息輸出到控制臺(tái),有些Handler可以把信息輸出到文件,還有些 Handler可以把信息發(fā)送到網(wǎng)絡(luò)上。如果覺得不夠用,還可以編寫自己的Handler。可以通過addHandler()方法添加多個(gè)多handler
Handler.setLevel(lel):指定被處理的信息級別,低于lel級別的信息將被忽略Handler.setFormatter():給這個(gè)handler選擇一個(gè)格式Handler.addFilter(filt)、Handler.removeFilter(filt):新增或刪除一個(gè)filter對象
每個(gè)Logger可以附加多個(gè)Handler。接下來我們就來介紹一些常用的Handler:
logging.handlers.RotatingFileHandler
這個(gè)Handler類似于上面的FileHandler,但是它可以管理文件大小。當(dāng)文件達(dá)到一定大小之后,它會(huì)自動(dòng)將當(dāng)前日志文件改名,然后創(chuàng)建 一個(gè)新的同名日志文件繼續(xù)輸出。比如日志文件是chat.log。當(dāng)chat.log達(dá)到指定的大小之后,RotatingFileHandler自動(dòng)把 文件改名為chat.log.1。不過,如果chat.log.1已經(jīng)存在,會(huì)先把chat.log.1重命名為chat.log.2。。。最后重新創(chuàng)建 chat.log,繼續(xù)輸出日志信息。它的函數(shù)是:
?
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode兩個(gè)參數(shù)和FileHandler一樣。
?
logging.handlers.TimedRotatingFileHandler
這個(gè)Handler和RotatingFileHandler類似,不過,它沒有通過判斷文件大小來決定何時(shí)重新創(chuàng)建日志文件,而是間隔一定時(shí)間就 自動(dòng)創(chuàng)建新的日志文件。重命名的過程與RotatingFileHandler類似,不過新的文件不是附加數(shù)字,而是當(dāng)前時(shí)間。它的函數(shù)是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename參數(shù)和backupCount參數(shù)和RotatingFileHandler具有相同的意義。
interval
是時(shí)間間隔。
when
參數(shù)是一個(gè)字符串。表示時(shí)間間隔的單位,不區(qū)分大小寫。它有以下取值:
日志的formatter是個(gè)獨(dú)立的組件,可以跟handler組合
fh = logging.FileHandler("access.log")formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')fh.setFormatter(formatter) #把formmater綁定到fh上
如果你想對日志內(nèi)容進(jìn)行過濾,就可自定義一個(gè)filter
class IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日志""" def filter(self, record): #固定寫法 return "db backup" not in record.getMessage()#注意filter函數(shù)會(huì)返加True or False,logger根據(jù)此值決定是否輸出此日志
然后把這個(gè)filter添加到logger中
logger.addFilter(IgnoreBackupLogFilter())
下面的日志就會(huì)把符合filter條件的過濾掉
logger.debug("test ....")logger.info("test info ....")logger.warning("start to run db backup job ....")logger.error("test error ....")
一個(gè)同時(shí)輸出到屏幕、文件、帶filter的完成例子
import loggingclass IgnoreBackupLogFilter(logging.Filter): """忽略帶db backup 的日志""" def filter(self, record): #固定寫法 return "db backup" not in record.getMessage()#console handlerch = logging.StreamHandler()ch.setLevel(logging.INFO)#file handlerfh = logging.FileHandler('mysql.log')#fh.setLevel(logging.WARNING)#formatterformatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')#bind formatter to chch.setFormatter(formatter)fh.setFormatter(formatter)logger = logging.getLogger("Mysql")logger.setLevel(logging.DEBUG) #logger 優(yōu)先級高于其它輸出途徑的#add handler to logger instancelogger.addHandler(ch)logger.addHandler(fh)#add filterlogger.addFilter(IgnoreBackupLogFilter())logger.debug("test ....")logger.info("test info ....")logger.warning("start to run db backup job ....")logger.error("test error ....")View Code
文件自動(dòng)截?cái)嗬?/p>
import loggingfrom logging import handlerslogger = logging.getLogger(__name__)log_file = "timelog.log"#fh = handlers.RotatingFileHandler(filename=log_file,maxBytes=10,backupCount=3)fh = handlers.TimedRotatingFileHandler(filename=log_file,when="S",interval=5,backupCount=3)formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s')fh.setFormatter(formatter)logger.addHandler(fh)logger.warning("test1")logger.warning("test12")logger.warning("test13")logger.warning("test14")View Code
re模塊
正則表達(dá)式就是字符串的匹配規(guī)則,在多數(shù)編程語言里都有相應(yīng)的支持,python里對應(yīng)的模塊是re
'.' 默認(rèn)匹配除\n之外的任意一個(gè)字符,若指定flag DOTALL,則匹配任意字符,包括換行'^' 匹配字符開頭,若指定flags MULTILINE,這種也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)'$' 匹配字符結(jié)尾, 若指定flags MULTILINE ,re.search('foo.$','foo1\nfoo2\n',re.MULTILINE).group() 會(huì)匹配到foo1'*' 匹配*號前的字符0次或多次, re.search('a*','aaaabac') 結(jié)果'aaaa'' ' 匹配前一個(gè)字符1次或多次,re.findall("ab ","ab cd abb bba") 結(jié)果['ab', 'abb']'?' 匹配前一個(gè)字符1次或0次 ,re.search('b?','alex').group() 匹配b 0次'{m}' 匹配前一個(gè)字符m次 ,re.search('b{3}','alexbbbs').group() 匹配到'bbb''{n,m}' 匹配前一個(gè)字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 結(jié)果'abb', 'ab', 'abb']'|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 結(jié)果'ABC''(...)' 分組匹配, re.search("(abc){2}a(123|45)", "abcabca456c").group() 結(jié)果為'abcabca45''\A' 只從字符開頭匹配,re.search("\Aabc","alexabc") 是匹配不到的,相當(dāng)于re.match('abc',"alexabc") 或^'\Z' 匹配字符結(jié)尾,同$ '\d' 匹配數(shù)字0-9'\D' 匹配非數(shù)字'\w' 匹配[A-Za-z0-9]'\W' 匹配非[A-Za-z0-9]'s' 匹配空白字符、\t、\n、\r , re.search("\s ","ab\tc1\n3").group() 結(jié)果 '\t''(?P<name>...)' 分組匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 結(jié)果{'province': '3714', 'city': '81', 'birthday': '1993'}
Foo/|-- bin/| |-- foo||-- foo/| |-- tests/| | |-- __init__.py| | |-- test_main.py| || |-- __init__.py| |-- main.py||-- docs/| |-- conf.py| |-- abc.rst||-- setup.py|-- requirements.txt|-- README
簡要解釋一下:
conf 存配置文件的,(賬戶數(shù)據(jù)、日志的文件名或者格式,這些用戶可以配置的;)
?
來源:http://www.icode9.com/content-4-27711.html聯(lián)系客服