模塊就是py文件。python中能開闢做用域的只有函數、類和模塊。html
for循環不能開闢做用域,for循環內的變量爲全局變量。if...else...同for循環同樣。python
在Python中,一般有這三種方式來表示時間:時間戳、元組(struct_time)、格式化的時間字符串:正則表達式
(1)時間戳(timestamp) :一般來講,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量。算法
咱們運行「type(time.time())」,返回的是float類型。shell
1
2
3
4
5
|
#時間戳,時間戳是計算機可以識別的時間。
import
time
print
(time.time())
#返回當前時間的時間戳,其中time.time(),第一個time爲模塊名,第二個time爲方法
-
-
-
>
1493166727.099066
|
(2)格式化的時間字符串(Format String): ‘2017-04-26’數據庫
1
2
3
4
5
6
7
|
#時間字符串,是人可以看懂的時間。
print
(time.strftime(
"%Y-%m-%d %X"
))
#Y表明year,m爲mouth,d爲day,x爲時間
-
-
-
>
'2017-04-26 00:32:18'
print
(time.strftime("
%
Y:
%
m))
#年月日時間分割能夠更改,此處用「:」分割
-
-
-
>
'2017:04'
|
(3)元組(struct_time) :struct_time元組共有9個元素共九個元素:(年,月,日,時,分,秒,一年中第幾周,一年中第幾天等)編程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# 時間元組,結構化時間,是用來操做時間的。
import
time
c
=
time.localtime()
print
(c)
-
-
-
>time.struct_time(tm_year
=
2017
, tm_mon
=
4
, tm_mday
=
26
, tm_hour
=
16
, tm_min
=
30
, tm_sec
=
42
, tm_wday
=
2
, tm_yday
=
116
, tm_isdst
=
0
)
<br>
#經過操做結構化時間查看具體信息
y
=
c.tm_year
print
(y)
-
-
-
>
2017
m
=
c.tm_mon
print
(m)
-
-
-
>
4
d
=
c.tm_mday
print
(d)
-
-
-
>
26
|
時間戳轉化爲結構化時間:localtime/gmtimejson
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#時間戳轉化爲結構化時間localtime/gmtime
#gmtime爲世界標準時間,通常不使用。
#localtime爲東八區時間,爲咱們所在的時間,常使用localtime
c1
=
time.localtime(
3600
*
24
)
print
(c1)
#打印距離1970-1-1 00:00:00一天的時間信息
-
-
-
>time.struct_time(tm_year
=
1970
, tm_mon
=
1
, tm_mday
=
2
, tm_hour
=
8
, tm_min
=
0
, tm_sec
=
0
, tm_wday
=
4
, tm_yday
=
2
, tm_isdst
=
0
)
print
(c1.tm_year,c1.tm_mon,c1.tm_mday,c1.tm_hour,c1.tm_min)
-
-
-
>
1970
1
2
8
0
c2
=
time.gmtime(
3600
*
24
)
print
(c2)
-
-
-
>time.struct_time(tm_year
=
1970
, tm_mon
=
1
, tm_mday
=
2
, tm_hour
=
0
, tm_min
=
0
, tm_sec
=
0
, tm_wday
=
4
, tm_yday
=
2
, tm_isdst
=
0
)
print
(c2.tm_year,c2.tm_mon,c2.tm_mday,c2.tm_hour,c2.tm_min)
-
-
-
>
1970
1
2
0
0
|
1
|
<strong> <
/
strong>
|
結構化時間轉化爲時間戳:mktimeapi
1
2
3
|
#結構化時間轉化爲時間戳mktime
print
(time.mktime(time.localtime()))
#當前結構化時間轉化爲時間戳
-
-
-
>
1493196972.0
|
字符串時間轉化爲結構化時間:strptime安全
1
2
3
|
#字符串時間轉化爲結構化時間:strptime
print
(time.strptime(
"2017-03-16"
,
"%Y-%m-%d"
))
#字符串時間2017-03-16轉化爲結構化時間
-
-
-
>time.struct_time(tm_year
=
2017
, tm_mon
=
3
, tm_mday
=
16
, tm_hour
=
0
, tm_min
=
0
, tm_sec
=
0
, tm_wday
=
3
, tm_yday
=
75
, tm_isdst
=
-
1
)
|
結構化時間轉化爲字符串時間:strftime
1
2
3
|
#結構化時間轉化爲字符串時間:strftime
print
(time.strftime(
"%Y-%m-%d %X"
, time.localtime()))
#當前結構化時間轉化爲當前字符串時間
-
-
-
>
2017
-
04
-
26
17
:
07
:
05
|
結構化時間轉化爲時間字符串:asctime
1
2
3
4
5
6
|
#結構化時間轉化爲時間字符串:asctime
print
(time.asctime(time.localtime(
312343423
)))
#轉化成距離1970-1-1 00:00:00 時間312343423秒的時間字符串格式
-
-
-
>Sun Nov
25
10
:
03
:
43
1979
print
(time.asctime(time.localtime()))
#轉化成當前時間字符串格式
-
-
-
>Wed Apr
26
17
:
25
:
16
2017
|
時間戳轉化爲時間字符串:ctime
1
2
3
4
5
6
|
#時間戳轉化爲時間字符串:ctime
print
(time.ctime(
312343423
))
#轉化成距離1970-1-1 00:00:00 時間312343423秒的時間字符串格式
-
-
-
>Sun Nov
25
10
:
03
:
43
1979
print
(time.ctime())
#轉化成當前時間字符串格式
-
-
-
>Wed Apr
26
17
:
26
:
19
2017
|
其餘方法
1
2
|
#其餘方法
sleep(secs)
# 線程推遲指定的時間運行,單位爲秒。至關於IO操做。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
import
random
print
(random.random())
#輸出大於0且小於1之間的小數
-
-
-
>
0.03231288445315539
print
(random.randint(
1
,
5
))
# 隨機輸出大於等於1且小於等於5之間的整數,[1,5]
-
-
-
>
4
print
(random.randrange(
1
,
3
))
# 隨機輸出大於等於1且小於3之間的整數,[1,3)
-
-
-
>
2
print
(random.choice([
1
,
'2'
,[
3
,
4
]]))
#隨機取列表中的一個元素,結果爲1或者2或者[3,4]
-
-
-
>[
3
,
4
]
print
(random.sample([
1
,
'2'
,[
3
,
4
]],
2
))
#隨機取列表中任意2個元素
-
-
-
>[
1
, [
3
,
4
]]
print
(random.uniform(
1
,
3
))
#隨機取大於1小於3的小數
-
-
-
>
1.0122103690258861
item
=
[
1
,
2
,
3
,
4
,
5
]
print
(random.shuffle(item))
#直接輸出,什麼都沒有
-
-
-
>
None
random.shuffle(item)
print
(item)
-
-
-
>[
1
,
3
,
5
,
2
,
4
]
print
(item)
#再次打印結果和上一次輸出結果同樣,須要從新打亂才能輸出從新排序的列表
-
-
-
>[
1
,
3
,
5
,
2
,
4
]
random.shuffle(item)
print
(item)
-
-
-
>[
2
,
3
,
5
,
1
,
4
]
|
練習:隨機生成驗證碼,字母和數字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
def
v_code():
code
=
''
for
i
in
range
(
10
):
num
=
random.randint(
0
,
9
)
#隨機選擇0~9一個數字
alf1
=
chr
(random.randint(
65
,
90
))
#隨機選擇A~Z一個字母
alf2
=
chr
(random.randint(
97
,
122
))
#隨機選擇a~z一個字母
add
=
random.choice([num,alf1,alf2])
#隨機選擇num、alf一、alf2中一個
code
=
"".join([code,
str
(add)])
#拼接依次選到的元素
return
code
#返回驗證碼
print
(v_code())
-
-
-
>
48OIcy44rA
|
Python的hashlib提供了常見的摘要算法,如MD5,SHA1等等。
什麼是摘要算法呢?摘要算法又稱哈希算法、散列算法。它經過一個函數,把任意長度的數據轉換爲一個長度固定的數據串(一般用16進制的字符串表示)。
摘要算法就是經過摘要函數f()對任意長度的數據data計算出固定長度的摘要digest,目的是爲了發現原始數據是否被人篡改過。
摘要算法之因此能指出數據是否被篡改過,就是由於摘要函數是一個單向函數,計算f(data)很容易,但經過digest反推data卻很是困難。
並且,對原始數據作一個bit的修改,都會致使計算出的摘要徹底不一樣。
咱們以常見的摘要算法MD5爲例,計算出一個字符串的MD5值:
1
2
3
4
5
6
|
import
hashlib
md5
=
hashlib.md5()
# md5只是hashlib摘要算法的一種,可使用其餘摘要算法。md5使用較多。
md5.update(
'how to use md5 in python hashlib?'
.encode(
"utf8"
))
#使用.encode("utf8")或者加b強制轉換成二進制方式都不會報錯,在python2中不須要
print
(md5.hexdigest())
-
-
-
>d26a53750bc40b38b65a520292f69306
# 對應的惟一值
|
若是數據量很大,能夠分塊屢次調用update(),最後計算的結果是同樣的:
1
2
3
4
5
6
|
import
hashlib
md5
=
hashlib.md5()
md5.update(b
'how to use md5 in '
)
md5.update(b
'python hashlib?'
)
print
(md5.hexdigest())
-
-
-
>d26a53750bc40b38b65a520292f69306
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
import
hashlib
m
=
hashlib.md5()
m.update(
"hello"
.encode(
"utf8"
))
#計算hello的hash值
print
(m.hexdigest())
#以16進制的方式打印通過md5摘要算法計算的hello的hash值
-
-
-
>
5d41402abc4b2a76b9719d911017c592
m.update(
"hello"
.encode(
"utf8"
))
#計算hellohello的hash值
print
(m.hexdigest())
-
-
-
>
23b431acfeb41e15d466d75de822307c
n
=
hashlib.md5(
"world"
.encode(
"utf8"
))
n.update(b
"python"
)
print
(n.hexdigest())
-
-
-
>ff9360a32af52a8a18496b51ad7e6b3f
|
MD5是最多見的摘要算法,速度很快,生成結果是固定的128 bit字節,一般用一個32位的16進制字符串表示。
另外一種常見的摘要算法是SHA1,調用SHA1和調用MD5徹底相似:
1
2
3
4
5
6
7
|
import
hashlib
sha1
=
hashlib.sha1()
sha1.update(
'how to use sha1 in '
.encode(
"utf8"
))
sha1.update(b
'python hashlib?'
)
print
(sha1.hexdigest())
-
-
-
>
2c76b57293ce30acef38d98f6046927161b46a44
|
SHA1的結果是160 bit字節,一般用一個40位的16進制字符串表示。
比SHA1更安全的算法是SHA256和SHA512,不過越安全的算法越慢,並且摘要長度更長。
任何容許用戶登陸的網站都會存儲用戶登陸的用戶名和口令。如何存儲用戶名和口令呢?方法是存到數據庫表中:
1
2
3
4
5
|
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,這一方法經過對原始口令加一個複雜字符串來實現,俗稱「加鹽」:
1
|
hashlib.md5(
"salt"
.encode(
"utf8"
))
#「加鹽」的內容此時是salt,也能夠爲帳戶名xuyaping,字符串a,數字1等等
|
通過Salt處理的MD5口令,只要Salt不被黑客知道,即便用戶輸入簡單口令,也很難經過MD5反推明文口令。
可是若是有兩個用戶都使用了相同的簡單口令好比123456,在數據庫中,將存儲兩條相同的MD5值,這說明這兩個用戶的口令是同樣的。
有沒有辦法讓使用相同口令的用戶存儲不一樣的MD5呢?
若是假定用戶沒法修改登陸名,就能夠經過把登陸名做爲Salt的一部分來計算MD5,從而實現相同口令的用戶也存儲不一樣的MD5。
摘要算法在不少地方都有普遍的應用。要注意摘要算法不是加密算法,不能用於加密(由於沒法經過摘要反推明文),只能用於防篡改,
可是它的單向計算特性決定了能夠在不存儲明文口令的狀況下驗證用戶口令。
os模塊是與操做系統交互的一個接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
os.getcwd() 獲取當前工做目錄,即當前python腳本工做的目錄路徑
os.chdir() 當前目錄
os.chdir(
"dirname"
) 改變當前腳本工做目錄;至關於shell下cd
os.curdir 返回當前目錄: (
'.'
),至關於shell下cd.
os.pardir 獲取當前目錄的父目錄字符串名:(
'..'
),至關於shell下cd.. 返回上一層目錄
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所指向的文件或者目錄的最後修改時間
os.path.getsize(path) 返回path的大小
|
1
2
3
4
5
6
|
sys.argv 命令行參數
List
,第一個元素是程序自己路徑
sys.exit(n) 退出程序,正常退出時exit(
0
)
sys.version 獲取Python解釋程序的版本信息
sys.maxint 最大的
Int
值
sys.path 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
sys.platform 返回操做系統平臺名稱
|
不予以配置,查看默認狀況下輸出:
1
2
3
4
5
6
7
8
9
10
|
import
logging
logging.debug(
'debug message'
)
logging.info(
'info message'
)
logging.warning(
'warning message'
)
logging.error(
'error message'
)
logging.critical(
'critical message'
)
-
-
-
>WARNING:root:warning message
ERROR:root:error message
CRITICAL:root:critical message
|
默認狀況下Python的logging模塊將日誌打印到了標準輸出中,且只顯示了大於等於WARNING級別的日誌,這說明默認的日誌級別設置爲WARNING(日誌級別等級CRITICAL > ERROR > WARNING > INFO > DEBUG),默認的日誌格式爲日誌級別:Logger名稱:用戶輸出消息。
靈活配置日誌級別,日誌格式,輸出位置:
使用config
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import
logging
logging.basicConfig(level
=
logging.DEBUG,
# 配置日誌級別,默認輸出debug等級及等級更高的內容
format
=
'%(asctime)s--->%(filename)s[line:%(lineno)d]====>%(levelname)s::::%(message)s'
,
# 配置日誌顯示格式
datefmt
=
'%a, %d %b %Y %H:%M:%S'
,
# 配置時間格式
filename
=
'test.log'
,
# 配置文件路徑
filemode
=
'w'
)
# 配置文件權限
logging.debug(
'debug message'
)
logging.info(
'info message'
)
logging.warning(
'warning message'
)
logging.error(
'error message'
)
logging.critical(
'critical message'
)
|
日誌輸出內容test.log文本打開內容以下:
1
2
3
4
5
|
Tue,
02
May
2017
07
:
49
:
54
-
-
-
>日誌模塊.py[line:
9
]
=
=
=
=
>DEBUG::::debug message
Tue,
02
May
2017
07
:
49
:
54
-
-
-
>日誌模塊.py[line:
10
]
=
=
=
=
>INFO::::info message
Tue,
02
May
2017
07
:
49
:
54
-
-
-
>日誌模塊.py[line:
11
]
=
=
=
=
>WARNING::::warning message
Tue,
02
May
2017
07
:
49
:
54
-
-
-
>日誌模塊.py[line:
12
]
=
=
=
=
>ERROR::::error message
Tue,
02
May
2017
07
:
49
:
54
-
-
-
>日誌模塊.py[line:
13
]
=
=
=
=
>CRITICAL::::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用戶輸出的消息
使用logger對象來配置
與config比,可同時顯示在程序運行頁面屏幕和文件中,功能更多,推薦使用。
上述幾個例子中咱們瞭解到了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分別用以記錄不一樣級別的日誌信息),logging.basicConfig()(用默認日誌格式(Formatter)爲日誌系統創建一個默認的流處理器(StreamHandler),設置基礎配置(如日誌級別等)並加到root logger(根Logger)中)這幾個logging模塊級別的函數,另外還有一個模塊級別的函數是logging.getLogger([name])(返回一個logger對象,若是沒有指定名字將返回root logger)
先看一個最簡單的過程:
1
2
3
4
5
|
import
logging
logging.info(
'info message'
)
#不會被打印,由於等級不夠
logger
=
logging.getLogger()
print
(logger)
-
-
-
><RootLogger root (WARNING)>
|
示例1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
1
import
logging
2
3
logger
=
logging.getLogger()
#建立一個大對象
4
5
fh
=
logging.FileHandler(
"test_log"
)
#向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容
6
ch
=
logging.StreamHandler()
#向屏幕上發送內容
7
#logger.setLevel(logging.DEBUG) #設定輸出等級
8
fm
=
logging.Formatter(
"%(asctime)s %(message)s"
)
#這個也是一個對象,做用是:定義日誌格式
9
10
fh.setFormatter(fm)
#往文件裏寫內容
11
ch.setFormatter(fm)
#往屏幕上輸出內容
12
13
logger.addHandler(fh)
#對象,相似於吸別人內力,把fh吃掉
14
logger.addHandler(ch)
#對象,相似於吸別人內力,把ch吃掉
15
16
logger.debug(
"debug"
)
#輸出日誌的級別
17
logger.info(
"info"
)
18
logger.warning(
"warning"
)
19
logger.error(
"error"
)
20
logger.critical(
"critical"
)
|
執行結果:
1 會生成一個test_log的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。 2 文件內容以下: 3 2016-12-15 14:38:27,657 warning 4 2016-12-15 14:38:27,658 error 5 2016-12-15 14:38:27,658 critical 6 7 屏幕輸出信息以下: 8 2016-12-15 14:38:27,657 warning 9 2016-12-15 14:38:27,658 error 10 2016-12-15 14:38:27,658 critical
示例2: logger.setLevel("DEBUG") 調整日誌級別,控制日誌顯示信息,DEBUG顯示5條記錄
1 import logging 2 3 logger=logging.getLogger() #建立一個大對象 4 5 fh=logging.FileHandler("test_log") #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容 6 ch=logging.StreamHandler() #向屏幕上發送內容 7 8 fm=logging.Formatter("%(asctime)s %(message)s") #這個也是一個對象,做用是:定義日誌格式 9 10 fh.setFormatter(fm) #往文件裏寫內容 11 ch.setFormatter(fm) #往屏幕上輸出內容 12 13 logger.addHandler(fh) #對象,相似於吸別人內力,把fh吃掉 14 logger.addHandler(ch) #對象,相似於吸別人內力,把ch吃掉 15 logger.setLevel("DEBUG") #設置日誌級別,控制日誌輸入多少條信息 16 17 18 #-------------從這裏開始都是在操做log---------------- 19 20 logger.debug("debug") #輸出日誌的級別 21 logger.info("info") 22 logger.warning("warning") 23 logger.error("error") 24 logger.critical("critical")
執行結果:
1 會生成一個test_log的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。 2 文件內容以下: 3 2016-12-15 14:54:37,036 debug 4 2016-12-15 14:54:37,037 info 5 2016-12-15 14:54:37,038 warning 6 2016-12-15 14:54:37,038 error 7 2016-12-15 14:54:37,039 critical 8 9 屏幕輸出信息以下: 10 2016-12-15 14:54:37,036 debug 11 2016-12-15 14:54:37,037 info 12 2016-12-15 14:54:37,038 warning 13 2016-12-15 14:54:37,038 error 14 2016-12-15 14:54:37,039 critical
示例3: 寫成函數的形式,並有返回值
1 import logging 2 3 def logger(): 4 5 logger=logging.getLogger() #建立一個大對象 6 7 fh=logging.FileHandler("test_log") #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容 8 ch=logging.StreamHandler() #向屏幕上發送內容 9 10 fm=logging.Formatter("%(asctime)s %(message)s") #這個也是一個對象,做用是:定義日誌格式 11 12 fh.setFormatter(fm) #往文件裏寫內容 13 ch.setFormatter(fm) #往屏幕上輸出內容 14 15 logger.addHandler(fh) #對象,相似於吸別人內力,把fh吃掉 16 logger.addHandler(ch) #對象,相似於吸別人內力,把ch吃掉 17 logger.setLevel("DEBUG") #設置日誌級別,控制日誌輸入多少條信息 18 19 return logger 20 21 #-------------從這裏開始都是在操做log---------------- 22 logger=logger() #這個日誌就作成了一個接口,想在其它地方使用,直接調用他就能夠啦! 23 24 logger.debug("debug") #輸出日誌的級別 25 logger.info("info") 26 logger.warning("warning") 27 logger.error("error") 28 logger.critical("critical")
執行結果:
1 會生成一個test_log的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。 2 文件內容以下: 3 2016-12-15 14:54:37,036 debug 4 2016-12-15 14:54:37,037 info 5 2016-12-15 14:54:37,038 warning 6 2016-12-15 14:54:37,038 error 7 2016-12-15 14:54:37,039 critical 8 9 屏幕輸出信息以下: 10 2016-12-15 14:54:37,036 debug 11 2016-12-15 14:54:37,037 info 12 2016-12-15 14:54:37,038 warning 13 2016-12-15 14:54:37,038 error 14 2016-12-15 14:54:37,039 critical
示例4: 只在屏幕文件中寫入日誌,不在屏幕上面顯示
1 import logging 2 3 def logger(): 4 5 logger=logging.getLogger() #建立一個大對象 6 7 fh=logging.FileHandler("test_log") #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容 8 #ch=logging.StreamHandler() #向屏幕上發送內容 9 10 fm=logging.Formatter("%(asctime)s %(message)s") #這個也是一個對象,做用是:定義日誌格式 11 12 fh.setFormatter(fm) #往文件裏寫內容 13 #ch.setFormatter(fm) #往屏幕上輸出內容 14 15 logger.addHandler(fh) #對象,相似於吸別人內力,把fh吃掉 16 #logger.addHandler(ch) #對象,相似於吸別人內力,把ch吃掉 17 logger.setLevel("DEBUG") #設置日誌級別,控制日誌輸入多少條信息 18 19 return logger 20 21 #-------------從這裏開始都是在操做log---------------- 22 logger=logger() #這個日誌就作成了一個接口,在其它地方,直接調用他就能夠啦! 23 24 logger.debug("debug") #輸出日誌的級別 25 logger.info("info") 26 logger.warning("warning") 27 logger.error("error") 28 logger.critical("critical")
執行結果:
1 #會生成一個test_log的文件,同時往裏面寫入信息,不會在屏幕上面顯示信息。 2 #文件內容以下: 3 2016-12-15 14:54:37,036 debug 4 2016-12-15 14:54:37,037 info 5 2016-12-15 14:54:37,038 warning 6 2016-12-15 14:54:37,038 error 7 2016-12-15 14:54:37,039 critical
示例5:沒有根用戶
#若是咱們再建立兩個logger對象
1 import logging 2 3 logger1 = logging.getLogger('mylogger') #默認是根,這裏表明他是子用戶(兩個用戶是同級) 4 #logger1 = logging.getLogger('mylogger.sontree') #若是mylogger下再建立一個字對象,就用.sontree;等於他就是mylogger的下級對象。 5 logger1.setLevel(logging.DEBUG) #第一次是DEBUG級別 6 7 logger2 = logging.getLogger('mylogger') #默認是根,這裏表明他是子用戶(兩個用戶是同級) 8 logger2.setLevel(logging.INFO) #第二次是INFO級別,覆蓋第一次的級別,因此打印結果是INFO級別顯示 9 10 fh=logging.FileHandler("test_log-new") #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容 11 ch=logging.StreamHandler() #向屏幕上發送內容 12 13 logger1.addHandler(fh) 14 logger1.addHandler(ch) 15 16 logger2.addHandler(fh) 17 logger2.addHandler(ch)
執行結果:
1 logger1 and logger2各打印4條信息 2 生成一個test_log-new的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。 3 文件內容以下: 4 logger1 info message 5 logger1 warning message 6 logger1 error message 7 logger1 critical message 8 logger2 info message 9 logger2 warning message 10 logger2 error message 11 logger2 critical message 12 13 #屏幕上面顯示的內容 14 logger1 info message 15 logger1 warning message 16 logger1 error message 17 logger1 critical message 18 logger2 info message 19 logger2 warning message 20 logger2 error message 21 logger2 critical message
示例6:添加根用戶 (lgger和mylogger是父子關係) (注意日誌輸出問題)
1 import logging 2 3 logger = logging.getLogger() #根用戶(根用戶級別,沒有定義日誌級別,默認warning級別,因此是3條信息 4 5 logger1 = logging.getLogger('mylogger') #默認是根,這裏表明他是子用戶(兩個用戶是同級) 6 logger1.setLevel(logging.DEBUG) #第一次是DEBUG級別,默認是打印五條信息,可是他打印信息的時候,會先去找父,若是有父,他就會多打印一遍,因此輸出是10條信息 7 8 fh=logging.FileHandler("test_log-new") #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容 9 ch=logging.StreamHandler() #向屏幕上發送內容 10 11 logger.addHandler(ch) #添加一個根用戶 12 logger.addHandler(fh) 13 14 logger1.addHandler(fh) #添加一個子用戶 15 logger1.addHandler(ch) 16 17 #打印信息 18 logger.debug('logger debug message') 19 logger.info('logger info message') 20 logger.warning('logger warning message') 21 logger.error('logger error message') 22 logger.critical('logger critical message') 23 24 #打印4條信息 25 logger1.debug('logger1 debug message') 26 logger1.info('logger1 info message') 27 logger1.warning('logger1 warning message') 28 logger1.error('logger1 error message') 29 logger1.critical('logger1 critical message')
輸出結果:
1 生成一個test_log-new的文件,同時往裏面寫入信息,並在屏幕上面顯示相同信息。 2 文件內容以下: 3 logger warning message 4 logger error message 5 logger critical message #前三條是根輸出的三條信息 6 logger1 debug message #後10條是子輸出的10條信息,爲何會輸入10條呢? 7 logger1 debug message #第一次是DEBUG級別,默認是打印五條信息,可是他打印信息的時候,會先去找父,若是有父,他就會多打印一遍,因此輸出是5+5=10條信息 8 logger1 info message 9 logger1 info message 10 logger1 warning message 11 logger1 warning message 12 logger1 error message 13 logger1 error message 14 logger1 critical message 15 logger1 critical message 16 17 屏幕輸出內容以下: 18 logger warning message 19 logger error message 20 logger critical message 21 logger1 debug message 22 logger1 debug message 23 logger1 info message 24 logger1 info message 25 logger1 warning message 26 logger1 warning message 27 logger1 error message 28 logger1 error message 29 logger1 critical message 30 logger1 critical message
示例7:添加根用戶 (控制根用戶不輸入,只輸出子用戶信息)
1 import logging 2 3 logger = logging.getLogger() #根用戶(根用戶級別,沒有定義日誌級別,默認warning級別,因此是3條信息 4 5 logger1 = logging.getLogger('mylogger') #默認是根,這裏表明他是子用戶(兩個用戶是同級) 6 logger1.setLevel(logging.DEBUG) #第一次是DEBUG級別,默認是打印五條信息,可是他打印信息的時候,會先去找父,若是有父,他就會多打印一遍,因此輸出是10條信息 7 8 fh=logging.FileHandler("test_log-new") #向文件裏發送內容,而且給個參數,做用是:定義一個文件名,往文件裏寫入內容 9 ch=logging.StreamHandler() #向屏幕上發送內容 10 11 logger1.addHandler(fh) #添加一個子用戶 12 logger1.addHandler(ch) 13 14 #打印4條信息 15 logger1.debug('logger1 debug message') 16 logger1.info('logger1 info message') 17 logger1.warning('logger1 warning message') 18 logger1.error('logger1 error message') 19 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
logging庫提供了多個組件:Logger、Handler、Filter、Formatter。Logger對象提供應用程序可直接使用的接口,Handler發送日誌到適當的目的地,Filter提供了過濾日誌信息的方法,Formatter指定日誌顯示格式。
Logger是一個樹形層級結構,輸出信息以前都要得到一個Logger(若是沒有顯示的獲取則自動建立並使用root Logger)。
logger = logging.getLogger()返回一個默認的Logger也即root Logger,並應用默認的日誌級別、Handler和Formatter設置。
固然也能夠經過Logger.setLevel(lel)指定最低的日誌級別,可用的日誌級別有logging.DEBUG、logging.INFO、logging.WARNING、logging.ERROR、logging.CRITICAL。
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical()輸出不一樣級別的日誌,只有日誌等級大於或等於設置的日誌級別的日誌纔會被輸出。
以前咱們學習過用eval內置方法能夠將一個字符串轉成python對象,不過,eval方法是有侷限性的,對於普通的數據類型,json.loads和eval都能用,但遇到特殊類型的時候,eval就無論用了,因此eval的重點仍是一般用來執行一個字符串表達式,並返回表達式的值。
1
2
3
4
5
6
7
|
import
json
x
=
"[null,true,false,1]"
# print(eval(x))
-
-
-
>報錯
print
(json.loads(x))
-
-
-
>[null,true,false,
1
]
|
什麼是序列化?
咱們把對象(變量)從內存中變成可存儲或傳輸的過程稱之爲序列化,在Python中叫pickling,在其餘語言中也被稱之爲serialization,marshalling,flattening等等,都是一個意思。
序列化以後,就能夠把序列化後的內容寫入磁盤,或者經過網絡傳輸到別的機器上。
反過來,把變量內容從序列化的對象從新讀到內存裏稱之爲反序列化,即unpickling。
若是咱們要在不一樣的編程語言之間傳遞對象,就必須把對象序列化爲標準格式,好比XML,但更好的方法是序列化爲JSON,由於JSON表示出來就是一個字符串,能夠被全部語言讀取,也能夠方便地存儲到磁盤或者經過網絡傳輸。JSON不只是標準格式,而且比XML更快,並且能夠直接在Web頁面中讀取,很是方便。
JSON表示的對象就是標準的JavaScript語言的對象一個子集,JSON和Python內置的數據類型對應以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
import
json
i
=
10
s
=
'hello'
t
=
(
1
,
4
,
6
)
l
=
[
3
,
5
,
7
]
d
=
{
'name'
:
"yuan"
}
#序列化
json_str1
=
json.dumps(i)
#將整型i轉換爲json字符串形式
json_str2
=
json.dumps(s)
#將字符串'hello'轉換爲json字符串形式
json_str3
=
json.dumps(t)
#將元組t=(1,4,6)轉換爲json字符串形式
json_str4
=
json.dumps(l)
#將列表l=[3,5,7]轉換爲json字符串形式
json_str5
=
json.dumps(d)
#將字典d={'name':"yuan"}轉換爲json字符串形式。當d有英文時,打印出的是unicode數據;當d內容爲英語時,正常顯示
print
(json_str1)
#json能識別整型
-
-
-
>
10
#json的字符串10
print
(json_str2)
#json不能識別字符串
-
-
-
>
"hello"
#打印雙引號,jason識別不了單引號''
print
(json_str3)
#json不能識別元組,識別不了(),默認轉換爲[]
-
-
-
>[
1
,
4
,
6
]
print
(json_str4)
#json能識別列表
-
-
-
>[
3
,
5
,
7
]
print
(json_str5)
#json能識別字典。jason識別不了單引號'',因此輸出的都是雙引號。
-
-
-
>{
"name"
:
"yuan"
}
|
python在文本中的使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#序列化
import
json
dic
=
{
'name'
:
'alvin'
,
'age'
:
23
,
'sex'
:
'male'
}
print
(
type
(dic))
-
-
-
><
class
'dict'
>
data
=
json.dumps(dic)
print
(
"type"
,
type
(data))
-
-
-
><
class
'str'
>
print
(
"data"
,data)
f
=
open
(
'序列化對象'
,
'w'
)
f.write(data)
#等價於json.dump(dic,f)
f.close()
#反序列化
import
json
f
=
open
(
'序列化對象'
)
new_data
=
json.loads(f.read())
#等價於data=json.load(f)
print
(
type
(new_data))
|
json序列化
把字典轉換成json形式的字符串寫入文件中 (兩種方法效果同樣,只是寫法不一樣而已)
方法一:推薦用這種方法
1 #一、把字典轉換成json形式的字符串寫入文件中 2 import json 3 dic = {'name': 'xuyaping'} 4 dic = json.dumps(dic) 5 f = open("hello", "w") 6 f.write(dic)
方法二:
1 import json 2 dic = {'name': 'xuyaping'} 3 f = open("hello", "w") 4 dic = json.dump(dic, f)
執行結果:
會生成一個hello的文件,並寫入內容:
1 {"name": "xuyaping"}
json反序列化
先建立一個json_test文件,寫入內容
1 {"name":"alvin"} #只要符合json規範就能夠把值取出來。 另外一種示例:{'name':"alvin"} #若是是'name' 的值是單引號就會報錯。
再去取值
1 import json 2 3 with open("Json_test","r") as f: #雙引號能夠直接把值取出來 4 data=f.read() 5 data=json.loads(data) 6 print(data["name"])
執行結果:
1 alvin
注:不管數據是怎樣建立的,只要知足json格式,就能夠json.loads出來,不必定非要dumps的數據才能loads
能夠轉換爲任意數據類型,比json轉換數據類型豐富不少。pickle序列化後的結果爲字節格式,json序列化後的結果爲字符串格式。
pickle,徹底爲python設定的。不一樣語言之間用json。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
#序列化
import
pickle
dic
=
{
'name'
:
'alvin'
,
'age'
:
23
,
'sex'
:
'male'
}
print
(
type
(dic))
-
-
-
><
class
'dict'
>
j
=
pickle.dumps(dic)
#pickle.dumps()序列化爲字節。
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保存那些不重要的數據,不能成功地反序列化也不要緊。
總結:
Json模塊提供了四個功能:dumps、dump、loads、load
pickle模塊提供了四個功能:dumps、dump、loads、load
dump()函數接受一個文件句柄和一個數據對象做爲參數,把數據對象以特定的格式保存 到給定的文件中。當咱們使用load()函數從文件中取出已保存的對象時,pickle知道如何恢復這些對象到它們原本的格式。
dumps()函數執行和dump() 函數相同的序列化。取代接受流對象並將序列化後的數據保存到磁盤文件,這個函數簡單的返回序列化的數據。
loads()函數執行和load() 函數同樣的反序列化。取代接受一個流對象並去文件讀取序列化後的數據,它接受包含序列化後的數據的str對象, 直接返回的對象。
就其本質而言,正則表達式(或 RE)是一種小型的、高度專業化的編程語言,(在Python中)它內嵌在Python中,並經過 re 模塊實現。正則表達式模式被編譯成一系列的字節碼,而後由用 C 編寫的匹配引擎執行。
字符匹配(普通字符,元字符):有特殊功能的符號,正則表達式最核心的部分。
1 普通字符:大多數字符和字母都會和自身匹配。
>>> re.findall('alvin','yuanaleSxalexwupeiqi') #re.findall,將符合條件的所有返還放到列表中。
['alvin']
2 元字符:. ^ $ * + ? { } [ ] | ( ) \
. 匹配任何一個除換行符之外的任意字符。
^ 匹配之前面字符開頭的任意字符。^ 放在[]中是取反的意思。
$ 匹配之後面字符結尾的任意字符。
* 將前面的符號匹配0到無窮次。
+ 將前面的符號匹配1到無窮次。
? 將前面的符號匹配0次或者1次。
{} {n,m} 將前面的符號匹配n到m次。
[] 字符集,或的關係。把通配符看成普通符號,沒有意義 ,除了 - ^ \外。
| 或
() 分組,涉及到分組,優先把分組內容顯示出來,匹配的只是分組的內容。
?: 取消優先級,取消分組特權。
\ 轉義符號。
徹底匹配,找什麼就是什麼。python內置的方法都是徹底匹配。
1
2
3
4
5
6
7
8
|
#徹底匹配
import
re
s
=
"hello world"
print
(s.replace(
"w"
,
"W"
))
-
-
-
>hello World
print
(s.find(
"w"
))
-
-
-
>
6
#6爲索引值
|
模糊匹配,如\d表明數字,\d+表明1到正無窮個數字。
1
2
3
4
5
6
7
8
|
import
re
l1
=
re.findall(
"\d"
,
"vbdkvbl1349vdkb358cnkvh3750jfg"
)
print
(l1)
-
-
-
>[
'1'
,
'3'
,
'4'
,
'9'
,
'3'
,
'5'
,
'8'
,
'3'
,
'7'
,
'5'
,
'0'
]
l2
=
re.findall(
"\d+"
,
"vbdkvbl1349vdkb358cnkvh3750jfg"
)
print
(l2)
-
-
-
>[
'1349'
,
'358'
,
'3750'
]
|
. 匹配任何一個除換行符之外的任意字符。
\t能夠匹配成功。\n不能夠匹配,除了\n不能匹配,其餘都能匹配。
* 將前面的符號b匹配0到無窮次
+將前面的符號b匹配1到無窮次
匹配失敗。
?將前面的符號匹配0次或者1次。
{3} 將前面的符號匹配3次。
{3,5} 將前面的符號匹配3到5次.
匹配北京電話號碼
ab{0,}至關於ab*
ab{0,}至關於ab+
[] 字符集,或的關係。
[bd] 匹配b或d
[b,d] 匹配b或,或d 三個字符
沒有a,c因此沒匹配出來
[] ,把通配符看成普通符號,沒有意義 。
[*] ,其中*只是普通符號,沒有意義 。
[] ,把元字符看成普通符號,除了 - ^ \外,其餘沒有意義 。
匹配失敗。
^ 開頭
匹配以yuan開頭的字符
$ 結尾
匹配以yuan結尾的字符
[0-9]和\d徹底同樣。 [a-z]和\w同樣。^ 放在[]中是取反的意思。
() 分組
(ad) 分組。由於涉及到分組,優先把分組內容顯示出來,匹配的只是分組的內容。
?: 取消優先級,取消分組特權。
| 或的意思。
將乘法運算過濾出來
\* 將*轉化爲普通字符。
\d+\.?\d* \d+匹配數字,\.將.轉化爲普通字符 , ?\d*匹配0到無窮個小數點。
- 不加打印出結果也是同樣的。
特殊符號使用\轉義沒效果,只針對普通字符。
\s 匹配空格。
\b 匹配特殊符號和邊界的。
加 r的緣由
c\\\l ,\\\一個是匹配\ ,一個是轉義\,一個是python解釋器翻譯\
加 r也能實現。
r 告訴python解釋器不要進行轉義。
\b 在ascii表中有一個功能。
\d 在ascii表中沒有一個功能,Python解釋器不認識,因此直接送給正則。
通常狀況下都加上r。
re.findall() 返回的是列表。
re.finditer() 返回的是迭代器。
re.search()與re.findall()不一樣的是匹配到第一個信息後就不向下匹配了。當返回None表示沒有匹配成功。
search和findall 不同的是須要group() ,且search匹配一個就中止。
re.split() 分割
re.split() 第三個參數設置分割次數。
re.sub() 替換
第三個參數count爲替換次數
re.sbn()將替換的次數也打印出來。
re.compile 編譯方法。
好處:效率高。對相同字符串編譯處理屢次,提升效率。
命名分組
?P<author> 想當於給每一個匹配的內容取個名字。
非貪婪匹配與貪婪匹配
後面字符串也要加r,由於\n python解釋器能識別,因此須要轉化成原生字符串給python解釋器。
經常使用正則表達式符號
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
'.'
默認匹配除\n以外的任意一個字符,若指定flag DOTALL,則匹配任意字符,包括換行
'^'
匹配字符開頭,若指定flags MULTILINE,這種也能夠匹配上(r
"^a"
,
"\nabc\neee"
,flags
=
re.MULTILINE)
'$'
匹配字符結尾,或e.search(
"foo$"
,
"bfoo\nsdfsf"
,flags
=
re.MULTILINE).group()也能夠
'*'
匹配
*
號前的字符
0
次或屢次,re.findall(
"ab*"
,
"cabb3abcbbac"
) 結果爲[
'abb'
,
'ab'
,
'a'
]
'+'
匹配前一個字符
1
次或屢次,re.findall(
"ab+"
,
"ab+cd+abb+bba"
) 結果[
'ab'
,
'abb'
]
'?'
匹配前一個字符
1
次或
0
次
'{m}'
匹配前一個字符m次
'{n,m}'
匹配前一個字符n到m次,re.findall(
"ab{1,3}"
,
"abb abc abbcbbb"
) 結果
'abb'
,
'ab'
,
'abb'
]
'|'
匹配|左或|右的字符,re.search(
"abc|ABC"
,
"ABCBabcCD"
).group() 結果
'ABC'
'(...)'
分組匹配,re.search(
"(abc){2}a(123|456)c"
,
"abcabca456c"
).group() 結果 abcabca456c
'\A'
只從字符開頭匹配,re.search(
"\Aabc"
,
"alexabc"
) 是匹配不到的
'\Z'
匹配字符結尾,同$
'\d'
匹配數字
0
-
9
'\D'
匹配非數字
'\w'
匹配[A
-
Za
-
z0
-
9
]
'\W'
匹配非[A
-
Za
-
z0
-
9
]
's'
匹配空白字符、\t、\n、\r , re.search(
"\s+"
,
"ab\tc1\n3"
).group() 結果
'\t'
'(?P<name>...)'
分組匹配 re.search(
"(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})"
,
"371481199306143242"
).groupdict(
"city"
) 結果{
'province'
:
'3714'
,
'city'
:
'81'
,
'birthday'
:
'1993'
}
|
最經常使用的匹配語法
1
2
3
4
5
|
re.match 從頭開始匹配
re.search 匹配包含
re.findall 把全部匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符當作列表分隔符
re.sub 匹配字符並替換
|
反斜槓的困擾
與大多數編程語言相同,正則表達式裏使用"\"做爲轉義字符,這就可能形成反斜槓困擾。假如你須要匹配文本中的字符"\",那麼使用編程語言表示的正則表達式裏將須要4個反斜槓"\\\\":前兩個和後兩個分別用於在編程語言裏轉義成反斜槓,轉換成兩個反斜槓後再在正則表達式裏轉義成一個反斜槓。Python裏的原生字符串很好地解決了這個問題,這個例子中的正則表達式可使用r"\\"表示。一樣,匹配一個數字的"\\d"能夠寫成r"\d"。有了原生字符串,你不再用擔憂是否是漏寫了反斜槓,寫出來的表達式也更直觀。
僅需輕輕知道的幾個匹配模式
1
2
3
|
re.I(re.IGNORECASE): 忽略大小寫(括號內是完整寫法,下同)
M(MULTILINE): 多行模式,改變
'^'
和
'$'
的行爲(參見上圖)
S(DOTALL): 點任意匹配模式,改變
'.'
的行爲
|