python 經常使用模塊 time random os模塊 sys模塊 json & pickle shelve模塊 xml模塊 configparser hashlib subprocess logg

 

python 經常使用模塊 time random os模塊 sys模塊 json & pickle shelve模塊 xml模塊 configparser hashlib  subprocess logging re正則

轉自老男孩老師Yuan:http://www.cnblogs.com/yuanchenqi/articles/5732581.htmljavascript

模塊&包(* * * * *)

模塊(modue)的概念:

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

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

使用模塊有什麼好處?node

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

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

因此,模塊一共三種:程序員

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

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

模塊導入方法

1 import 語句正則表達式

?
1
import module1[, module2[,... moduleN]

當咱們使用import語句的時候,Python解釋器是怎樣找到對應的文件的呢?答案就是解釋器有本身的搜索路徑,存在sys.path裏。  算法

?
1
2
[' ', ' / usr / lib / python3. 4 ', ' / usr / lib / python3. 4 / plat - x86_64 - linux - gnu',
'/usr/lib/python3.4/lib-dynload' , '/usr/local/lib/python3.4/dist-packages' , '/usr/lib/python3/dist-packages' ]  

所以若像我同樣在當前目錄下存在與要引入模塊同名的文件,就會把要引入的模塊屏蔽掉。

2  from…import 語句

?
1
from modname import name1[, name2[, ... nameN]]

這個聲明不會把整個modulename模塊導入到當前的命名空間中,只會將它裏面的name1或name2單個引入到執行這個聲明的模塊的全局符號表。

3  From…import* 語句

?
1
from modname import *

這提供了一個簡單的方法來導入一個模塊中的全部項目。然而這種聲明不應被過多地使用。大多數狀況, Python程序員不使用這種方法,由於引入的其它來源的命名,極可能覆蓋了已有的定義。

4 運行本質 

?
1
2
#1 import test
#2 from test import add  

不管1仍是2,首先經過sys.path找到test.py,而後執行test腳本(所有執行),區別是1會將test這個變量名加載到名字空間,而2只會將add這個變量名加載進來。  

包(package)

若是不一樣的人編寫的模塊名相同怎麼辦?爲了不模塊名衝突,Python又引入了按目錄來組織模塊的方法,稱爲包(Package)。

舉個例子,一個abc.py的文件就是一個名字叫abc的模塊,一個xyz.py的文件就是一個名字叫xyz的模塊。

如今,假設咱們的abcxyz這兩個模塊名字與其餘模塊衝突了,因而咱們能夠經過包來組織模塊,避免衝突。方法是選擇一個頂層包名:

                                           

引入了包之後,只要頂層的包名不與別人衝突,那全部模塊都不會與別人衝突。如今,view.py模塊的名字就變成了hello_django.app01.views,相似的,manage.py的模塊名則是hello_django.manage

請注意,每個包目錄下面都會有一個__init__.py的文件,這個文件是必須存在的,不然,Python就把這個目錄當成普通目錄(文件夾),而不是一個包。__init__.py能夠是空文件,也能夠有Python代碼,由於__init__.py自己就是一個模塊,而它的模塊名就是對應包的名字

調用包就是執行包下的__init__.py文件

 注意點(important)

1--------------

在nod1裏import  hello是找不到的,有同窗說能夠找到呀,那是由於你的pycharm爲你把myapp這一層路徑加入到了sys.path裏面,因此能夠找到,然而程序一旦在命令行運行,則報錯。有同窗問那怎麼辦?簡單啊,本身把這個路徑加進去不就OK啦:

?
1
2
3
4
5
import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)
import hello
hello.hello1()

2 --------------

?
1
2
if __name__ = = '__main__' :
     print ( 'ok' )

「Make a .py both importable and executable」

      若是咱們是直接執行某個.py文件的時候,該文件中那麼」__name__ == '__main__'「是True,可是咱們若是從另一個.py文件經過import導入該文件的時候,這時__name__的值就是咱們這個py文件的名字而不是__main__。

      這個功能還有一個用處:調試代碼的時候,在」if __name__ == '__main__'「中加入一些咱們的調試代碼,咱們可讓外部模塊調用的時候不執行咱們的調試代碼,可是若是咱們想排查問題的時候,直接執行該模塊文件,調試代碼可以正常運行!s

3   

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
##-------------cal.py
def add(x,y):
 
     return x + y
##-------------main.py
import cal      #from module import cal
 
def main():
 
     cal.add( 1 , 2 )
     
##--------------bin.py
from module import main
 
main.main()
# from module import cal 改爲 from . import cal一樣能夠,這是由於bin.py是咱們的執行腳本,
# sys.path裏有bin.py的當前環境。即/Users/yuanhao/Desktop/whaterver/project/web這層路徑,
# 不管import what ,  解釋器都會按這個路徑找。因此當執行到main.py時,import cal會找不到,由於
# sys.path裏沒有/Users/yuanhao/Desktop/whaterver/project/web/module這個路徑,而
#  from  module/.  import cal 時,解釋器就能夠找到了。
注意

time模塊(* * * *)

三種時間表示

在Python中,一般有這幾種方式來表示時間:

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

              

?
1
2
help (time)
help (time.asctime)

random模塊(* *)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import random
 
print (random.random()) #(0,1)----float
 
print (random.randint( 1 , 3 ))  #[1,3]
 
print (random.randrange( 1 , 3 )) #[1,3)
 
print (random.choice([ 1 , '23' ,[ 4 , 5 ]])) #23
 
print (random.sample([ 1 , '23' ,[ 4 , 5 ]], 2 )) #[[4, 5], '23']
 
print (random.uniform( 1 , 3 )) #1.927109612082716
 
 
item = [ 1 , 3 , 5 , 7 , 9 ]
random.shuffle(item)
print (item)
import random

def v_code():

    code = ''
    for i in range(5):

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

print(v_code())
驗證碼

 os模塊(* * * *)

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

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

sys模塊(* * *)

?
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       返回操做系統平臺名稱

進度條:

import sys,time
for i in range(10):
    sys.stdout.write('#')
    time.sleep(1)
    sys.stdout.flush()
View Code

json & pickle(* * * *)

以前咱們學習過用eval內置方法能夠將一個字符串轉成python對象,不過,eval方法是有侷限性的,對於普通的數據類型,json.loads和eval都能用,但遇到特殊類型的時候,eval就無論用了,因此eval的重點仍是一般用來執行一個字符串表達式,並返回表達式的值。

?
1
2
3
4
import json
x = "[null,true,false,1]"
print ( eval (x))
print (json.loads(x))

什麼是序列化?

咱們把對象(變量)從內存中變成可存儲或傳輸的過程稱之爲序列化,在Python中叫pickling,在其餘語言中也被稱之爲serialization,marshalling,flattening等等,都是一個意思。

序列化以後,就能夠把序列化後的內容寫入磁盤,或者經過網絡傳輸到別的機器上。

反過來,把變量內容從序列化的對象從新讀到內存裏稱之爲反序列化,即unpickling。

json

若是咱們要在不一樣的編程語言之間傳遞對象,就必須把對象序列化爲標準格式,好比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
#----------------------------序列化
import json
 
dic = { 'name' : 'alvin' , 'age' : 23 , 'sex' : 'male' }
print ( type (dic)) #<class 'dict'>
 
j = json.dumps(dic)
print ( type (j)) #<class 'str'>
 
 
f = open ( '序列化對象' , 'w' )
f.write(j)  #-------------------等價於json.dump(dic,f)
f.close()
#-----------------------------反序列化<br>
import json
f = open ( '序列化對象' )
data = json.loads(f.read()) #  等價於data=json.load(f)
import json
#dct="{'1':111}"#json 不認單引號
#dct=str({"1":111})#報錯,由於生成的數據仍是單引號:{'one': 1}

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

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

pickle 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
##----------------------------序列化
import pickle
 
dic = { 'name' : 'alvin' , 'age' : 23 , 'sex' : 'male' }
 
print ( type (dic)) #<class 'dict'>
 
j = pickle.dumps(dic)
print ( type (j)) #<class 'bytes'>
 
 
f = open ( '序列化對象_pickle' , 'wb' ) #注意是w是寫入str,wb是寫入bytes,j是'bytes'
f.write(j)  #-------------------等價於pickle.dump(dic,f)
 
f.close()
#-------------------------反序列化
import pickle
f = open ( '序列化對象_pickle' , 'rb' )
 
data = pickle.loads(f.read()) #  等價於data=pickle.load(f)
 
 
print (data[ 'age' ])    

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

shelve模塊(* * *)

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

?
1
2
3
4
5
6
7
8
9
10
11
12
import shelve
 
f = shelve. open (r 'shelve.txt' )
 
# f['stu1_info']={'name':'alex','age':'18'}
# f['stu2_info']={'name':'alvin','age':'20'}
# f['school_info']={'website':'oldboyedu.com','city':'beijing'}
#
#
# f.close()
 
print (f.get( 'stu_info' )[ 'age' ])

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:

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

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")
 
tree.write("xmltest.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

本身建立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) #打印生成的格式
建立xml文檔

configparser模塊(* *)

來看一個好多軟件的常見文檔格式以下:

?
1
2
3
4
5
6
7
8
9
10
11
12
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
  
[bitbucket.org]
User = hg
  
[topsecret.server.com]
Port = 50022
ForwardX11 = no

若是想用python生成一個這樣的文檔怎麼作呢?

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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' <br>
with open ( 'example.ini' , 'w' ) as configfile:
    config.write(configfile)
import configparser

config = configparser.ConfigParser()

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

config.read('example.ini')

print(config.sections())   #['bitbucket.org', 'topsecret.server.com']

print('bytebong.com' in config)# False

print(config['bitbucket.org']['User']) # hg

print(config['DEFAULT']['Compression']) #yes

print(config['topsecret.server.com']['ForwardX11'])  #no


for key in config['bitbucket.org']:
    print(key)


# user
# serveraliveinterval
# compression
# compressionlevel
# forwardx11


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

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


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


config.add_section('yuan')

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

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

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

hashlib模塊(* *)

用於加密相關的操做,3.x裏代替了md5模塊和sha模塊,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import hashlib
 
m = hashlib.md5() # m=hashlib.sha256()
 
m.update( 'hello' .encode( 'utf8' ))
print (m.hexdigest())  #5d41402abc4b2a76b9719d911017c592
 
m.update( 'alvin' .encode( 'utf8' ))
 
print (m.hexdigest())  #92a7e713c30abbb0319fa07da2a5c4af
 
m2 = hashlib.md5()
m2.update( 'helloalvin' .encode( 'utf8' ))
print (m2.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af

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

?
1
2
3
4
5
6
7
import hashlib
 
# ######## 256 ########
 
hash = hashlib.sha256( '898oaFs09f' .encode( 'utf8' ))
hash .update( 'alvin' .encode( 'utf8' ))
print ( hash .hexdigest()) #e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7

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

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

subprocess模塊(* * * *)

      當咱們須要調用系統的命令的時候,最早考慮的os模塊。用os.system()和os.popen()來進行操做。可是這兩個命令過於簡單,不能完成一些複雜的操做,如給運行的命令提供輸入或者讀取命令的輸出,判斷該命令的運行狀態,管理多個命令的並行等等。這時subprocess中的Popen命令就能有效的完成咱們須要的操做。

      subprocess模塊容許一個進程建立一個新的子進程,經過管道鏈接到子進程的stdin/stdout/stderr,獲取子進程的返回值等操做。 

The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes.

This module intends to replace several other, older modules and functions, such as: os.system、os.spawn*、os.popen*、popen2.*、commands.*

 

這個模塊一個類:Popen。

?
1
2
3
#Popen它的構造函數以下:
 
subprocess.Popen(args, bufsize = 0 , executable = None , stdin = None , stdout = None ,stderr = None , preexec_fn = None , close_fds = False , shell = False ,<br>                 cwd = None , env = None , universal_newlines = False , startupinfo = None , creationflags = 0 )
# 參數args能夠是字符串或者序列類型(如:list,元組),用於指定進程的可執行文件及其參數。
# 若是是序列類型,第一個元素一般是可執行文件的路徑。咱們也能夠顯式的使用executeable參
# 數來指定可執行文件的路徑。在windows操做系統上,Popen經過調用CreateProcess()來創
# 建子進程,CreateProcess接收一個字符串參數,若是args是序列類型,系統將會經過
# list2cmdline()函數將序列類型轉換爲字符串。
# 
# 
# 參數bufsize:指定緩衝。我到如今還不清楚這個參數的具體含義,望各個大牛指點。
# 
# 參數executable用於指定可執行程序。通常狀況下咱們經過args參數來設置所要運行的程序。如
# 果將參數shell設爲True,executable將指定程序使用的shell。在windows平臺下,默認的
# shell由COMSPEC環境變量來指定。
# 
# 參數stdin, stdout, stderr分別表示程序的標準輸入、輸出、錯誤句柄。他們能夠是PIPE,
# 文件描述符或文件對象,也能夠設置爲None,表示從父進程繼承。
# 
# 參數preexec_fn只在Unix平臺下有效,用於指定一個可執行對象(callable object),它將
# 在子進程運行以前被調用。
# 
# 參數Close_sfs:在windows平臺下,若是close_fds被設置爲True,則新建立的子進程將不會
# 繼承父進程的輸入、輸出、錯誤管道。咱們不能將close_fds設置爲True同時重定向子進程的標準
# 輸入、輸出與錯誤(stdin, stdout, stderr)。
# 
# 若是參數shell設爲true,程序將經過shell來執行。
# 
# 參數cwd用於設置子進程的當前目錄。
# 
# 參數env是字典類型,用於指定子進程的環境變量。若是env = None,子進程的環境變量將從父
# 進程中繼承。
# 
# 參數Universal_newlines:不一樣操做系統下,文本的換行符是不同的。如:windows下
# 用’/r/n’表示換,而Linux下用’/n’。若是將此參數設置爲True,Python統一把這些換行符當
# 做’/n’來處理。
# 
# 參數startupinfo與createionflags只在windows下用效,它們將被傳遞給底層的
# CreateProcess()函數,用於設置子進程的一些屬性,如:主窗口的外觀,進程的優先級等等。
parameter

簡單命令:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import subprocess
 
a = subprocess.Popen( 'ls' ) #  建立一個新的進程,與主進程不一樣步
 
print ( '>>>>>>>' ,a) #a是Popen的一個實例對象
 
'''
>>>>>>> <subprocess.Popen object at 0x10185f860>
__init__.py
__pycache__
log.py
main.py
 
'''
 
# subprocess.Popen('ls -l',shell=True)
 
# subprocess.Popen(['ls','-l'])

subprocess.PIPE

在建立Popen對象時,subprocess.PIPE能夠初始化stdin, stdout或stderr參數。表示與子進程通訊的標準流。

?
1
2
3
4
5
6
import subprocess
 
# subprocess.Popen('ls')
p = subprocess.Popen( 'ls' ,stdout = subprocess.PIPE) #結果跑哪去啦?
 
print (p.stdout.read()) #這這呢:b'__pycache__\nhello.py\nok.py\nweb\n'

這是由於subprocess建立了子進程,結果本在子進程中,if 想要執行結果轉到主進程中,就得須要一個管道,即 : stdout=subprocess.PIPE

subprocess.STDOUT

建立Popen對象時,用於初始化stderr參數,表示將錯誤經過標準輸出流輸出。

Popen的方法

Popen.poll() 
用於檢查子進程是否已經結束。設置並返回returncode屬性。

Popen.wait() 
等待子進程結束。設置並返回returncode屬性。

Popen.communicate(input=None)
與子進程進行交互。向stdin發送數據,或從stdout和stderr中讀取數據。可選參數input指定發送到子進程的參數。 Communicate()返回一個元組:(stdoutdata, stderrdata)。注意:若是但願經過進程的stdin向其發送數據,在建立Popen對象的時候,參數stdin必須被設置爲PIPE。一樣,如 果但願從stdout和stderr獲取數據,必須將stdout和stderr設置爲PIPE。

Popen.send_signal(signal) 
向子進程發送信號。

Popen.terminate()
中止(stop)子進程。在windows平臺下,該方法將調用Windows API TerminateProcess()來結束子進程。

Popen.kill()
殺死子進程。

Popen.stdin 
若是在建立Popen對象是,參數stdin被設置爲PIPE,Popen.stdin將返回一個文件對象用於策子進程發送指令。不然返回None。

Popen.stdout 
若是在建立Popen對象是,參數stdout被設置爲PIPE,Popen.stdout將返回一個文件對象用於策子進程發送指令。不然返回 None。

Popen.stderr 
若是在建立Popen對象是,參數stdout被設置爲PIPE,Popen.stdout將返回一個文件對象用於策子進程發送指令。不然返回 None。

Popen.pid 
獲取子進程的進程ID。

Popen.returncode 
獲取進程的返回值。若是進程尚未結束,返回None。
View Code

supprocess模塊的工具函數

?
1
2
3
4
5
6
7
8
9
10
11
12
13
supprocess模塊提供了一些函數,方便咱們用於建立進程來實現一些簡單的功能。
 
subprocess.call( * popenargs, * * kwargs)
運行命令。該函數將一直等待到子進程運行結束,並返回進程的returncode。若是子進程不須要進行交 互,就可使用該函數來建立。
 
subprocess.check_call( * popenargs, * * kwargs)
與subprocess.call( * popenargs, * * kwargs)功能同樣,只是若是子進程返回的returncode不爲 0 的話,將觸發CalledProcessError異常。在異常對象中,包 括進程的returncode信息。
 
check_output( * popenargs, * * kwargs)
與call()方法相似,以byte string的方式返回子進程的輸出,若是子進程的返回值不是 0 ,它拋出CalledProcessError異常,這個異常中的returncode包含返回碼,output屬性包含已有的輸出。
 
getstatusoutput(cmd) / getoutput(cmd)
這兩個函數僅僅在Unix下可用,它們在shell中執行指定的命令cmd,前者返回(status, output),後者返回output。其中,這裏的output包括子進程的stdout和stderr。
import subprocess

#1
# subprocess.call('ls',shell=True)
'''
hello.py
ok.py
web
'''
# data=subprocess.call('ls',shell=True)
# print(data)
'''
hello.py
ok.py
web
0
'''

#2
# subprocess.check_call('ls',shell=True)

'''
hello.py
ok.py
web
'''
# data=subprocess.check_call('ls',shell=True)
# print(data)
'''
hello.py
ok.py
web
0
'''
# 兩個函數區別:只是若是子進程返回的returncode不爲0的話,將觸發CalledProcessError異常



#3
# subprocess.check_output('ls')#無結果

# data=subprocess.check_output('ls')
# print(data)  #b'hello.py\nok.py\nweb\n'
演示

 交互命令:

終端輸入的命令分爲兩種:

  • 輸入便可獲得輸出,如:ifconfig
  • 輸入進行某環境,依賴再輸入,如:python

須要交互的命令示例

待續

logging模塊(* * * * *)

一 (簡單應用)

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 > NOTSET),默認的日誌格式爲日誌級別:Logger名稱:用戶輸出消息。

 

二  靈活配置日誌級別,日誌格式,輸出位置

複製代碼
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='/tmp/test.log',  
                    filemode='w')  
  
logging.debug('debug message')  
logging.info('info message')  
logging.warning('warning message')  
logging.error('error message')  
logging.critical('critical message')
複製代碼

查看輸出:
cat /tmp/test.log 
Mon, 05 May 2014 16:29:53 test_logging.py[line:9] DEBUG debug message
Mon, 05 May 2014 16:29:53 test_logging.py[line:10] INFO info message
Mon, 05 May 2014 16:29:53 test_logging.py[line:11] WARNING warning message
Mon, 05 May 2014 16:29:53 test_logging.py[line:12] ERROR error message
Mon, 05 May 2014 16:29:53 test_logging.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對象

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

     先看一個最簡單的過程:

複製代碼
import logging

logger = logging.getLogger()
# 建立一個handler,用於寫入日誌文件
fh = logging.FileHandler('test.log')

# 再建立一個handler,用於輸出到控制檯
ch = logging.StreamHandler()

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh) #logger對象能夠添加多個fh和ch對象
logger.addHandler(ch)

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
複製代碼

      先簡單介紹一下,logging庫提供了多個組件:Logger、Handler、Filter、Formatter。Logger對象提供應用程序可直接使用的接口,Handler發送日誌到適當的目的地,Filter提供了過濾日誌信息的方法,Formatter指定日誌顯示格式。

     (1)

      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()輸出不一樣級別的日誌,只有日誌等級大於或等於設置的日誌級別的日誌纔會被輸出。 

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

只輸出了
2014-05-06 12:54:43,222 - root - WARNING - logger warning message
2014-05-06 12:54:43,223 - root - ERROR - logger error message
2014-05-06 12:54:43,224 - root - CRITICAL - logger critical message
     從這個輸出能夠看出logger = logging.getLogger()返回的Logger名爲root。這裏沒有用logger.setLevel(logging.Debug)顯示的爲logger設置日誌級別,因此使用默認的日誌級別WARNIING,故結果只輸出了大於等於WARNIING級別的信息。

     (2) 若是咱們再建立兩個logger對象: 

複製代碼
##################################################
logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG)

logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO)

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

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

logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message')
  
logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')
複製代碼

結果:

      

這裏有兩個個問題:

      <1>咱們明明經過logger1.setLevel(logging.DEBUG)將logger1的日誌級別設置爲了DEBUG,爲什麼顯示的時候沒有顯示出DEBUG級別的日誌信息,而是從INFO級別的日誌開始顯示呢?

       原來logger1和logger2對應的是同一個Logger實例,只要logging.getLogger(name)中名稱參數name相同則返回的Logger實例就是同一個,且僅有一個,也即name與Logger實例一一對應。在logger2實例中經過logger2.setLevel(logging.INFO)設置mylogger的日誌級別爲logging.INFO,因此最後logger1的輸出聽從了後來設置的日誌級別。

      <2>爲何logger一、logger2對應的每一個輸出分別顯示兩次?
       這是由於咱們經過logger = logging.getLogger()顯示的建立了root Logger,而logger1 = logging.getLogger('mylogger')建立了root Logger的孩子(root.)mylogger,logger2一樣。而孩子,孫子,重孫……既會將消息分發給他的handler進行處理也會傳遞給全部的祖先Logger處理。

        ok,那麼如今咱們把

# logger.addHandler(fh)

# logger.addHandler(ch)  註釋掉,咱們再來看效果:

 

由於咱們註釋了logger對象顯示的位置,因此才用了默認方式,即標準輸出方式。由於它的父級沒有設置文件顯示方式,因此在這裏只打印了一次。

孩子,孫子,重孫……可逐層繼承來自祖先的日誌級別、Handler、Filter設置,也能夠經過Logger.setLevel(lel)、Logger.addHandler(hdlr)、Logger.removeHandler(hdlr)、Logger.addFilter(filt)、Logger.removeFilter(filt)。設置本身特別的日誌級別、Handler、Filter。若不設置則使用繼承來的值。

<3>Filter
     限制只有知足過濾規則的日誌纔會輸出。
     好比咱們定義了filter = logging.Filter('a.b.c'),並將這個Filter添加到了一個Handler上,則使用該Handler的Logger中只有名字帶          a.b.c前綴的Logger才能輸出其日誌。

 

     filter = logging.Filter('mylogger') 

     logger.addFilter(filter)

     這是隻對logger這個對象進行篩選

     若是想對全部的對象進行篩選,則:

      filter = logging.Filter('mylogger') 

      fh.addFilter(filter)

      ch.addFilter(filter)

      這樣,全部添加fh或者ch的logger對象都會進行篩選。

完整代碼1:

import logging

logger = logging.getLogger()
# 建立一個handler,用於寫入日誌文件
fh = logging.FileHandler('test.log')

# 再建立一個handler,用於輸出到控制檯
ch = logging.StreamHandler()

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

fh.setFormatter(formatter)
ch.setFormatter(formatter)

# 定義一個filter
filter = logging.Filter('mylogger')
fh.addFilter(filter)
ch.addFilter(filter)

# logger.addFilter(filter)
logger.addHandler(fh)
logger.addHandler(ch)




logger.setLevel(logging.DEBUG)

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

##################################################
logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG)

logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO)

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

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

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

logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')
View Code

       完整代碼2:

#coding:utf-8  
import logging  
  
# 建立一個logger    
logger = logging.getLogger()  
  
logger1 = logging.getLogger('mylogger')  
logger1.setLevel(logging.DEBUG)  
  
logger2 = logging.getLogger('mylogger')  
logger2.setLevel(logging.INFO)  
  
logger3 = logging.getLogger('mylogger.child1')  
logger3.setLevel(logging.WARNING)  
  
logger4 = logging.getLogger('mylogger.child1.child2')  
logger4.setLevel(logging.DEBUG)  
  
logger5 = logging.getLogger('mylogger.child1.child2.child3')  
logger5.setLevel(logging.DEBUG)  
  
# 建立一個handler,用於寫入日誌文件    
fh = logging.FileHandler('/tmp/test.log')  
  
# 再建立一個handler,用於輸出到控制檯    
ch = logging.StreamHandler()  
  
# 定義handler的輸出格式formatter    
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')  
fh.setFormatter(formatter)  
ch.setFormatter(formatter)  
  
#定義一個filter  
#filter = logging.Filter('mylogger.child1.child2')  
#fh.addFilter(filter)    
  
# 給logger添加handler    
#logger.addFilter(filter)  
logger.addHandler(fh)  
logger.addHandler(ch)  
  
#logger1.addFilter(filter)  
logger1.addHandler(fh)  
logger1.addHandler(ch)  
  
logger2.addHandler(fh)  
logger2.addHandler(ch)  
  
#logger3.addFilter(filter)  
logger3.addHandler(fh)  
logger3.addHandler(ch)  
  
#logger4.addFilter(filter)  
logger4.addHandler(fh)  
logger4.addHandler(ch)  
  
logger5.addHandler(fh)  
logger5.addHandler(ch)  
  
# 記錄一條日誌    
logger.debug('logger debug message')  
logger.info('logger info message')  
logger.warning('logger warning message')  
logger.error('logger error message')  
logger.critical('logger critical message')  
  
logger1.debug('logger1 debug message')  
logger1.info('logger1 info message')  
logger1.warning('logger1 warning message')  
logger1.error('logger1 error message')  
logger1.critical('logger1 critical message')  
  
logger2.debug('logger2 debug message')  
logger2.info('logger2 info message')  
logger2.warning('logger2 warning message')  
logger2.error('logger2 error message')  
logger2.critical('logger2 critical message')  
  
logger3.debug('logger3 debug message')  
logger3.info('logger3 info message')  
logger3.warning('logger3 warning message')  
logger3.error('logger3 error message')  
logger3.critical('logger3 critical message')  
  
logger4.debug('logger4 debug message')  
logger4.info('logger4 info message')  
logger4.warning('logger4 warning message')  
logger4.error('logger4 error message')  
logger4.critical('logger4 critical message')  
  
logger5.debug('logger5 debug message')  
logger5.info('logger5 info message')  
logger5.warning('logger5 warning message')  
logger5.error('logger5 error message')  
logger5.critical('logger5 critical message')  
View Code

應用:     

import os
import time
import logging
from config import settings


def get_logger(card_num, struct_time):

    if struct_time.tm_mday < 23:
        file_name = "%s_%s_%d" %(struct_time.tm_year, struct_time.tm_mon, 22)
    else:
        file_name = "%s_%s_%d" %(struct_time.tm_year, struct_time.tm_mon+1, 22)

    file_handler = logging.FileHandler(
        os.path.join(settings.USER_DIR_FOLDER, card_num, 'record', file_name),
        encoding='utf-8'
    )
    fmt = logging.Formatter(fmt="%(asctime)s :  %(message)s")
    file_handler.setFormatter(fmt)

    logger1 = logging.Logger('user_logger', level=logging.INFO)
    logger1.addHandler(file_handler)
    return logger1
View Code

 re模塊(* * * * *)

就其本質而言,正則表達式(或 RE)是一種小型的、高度專業化的編程語言,(在Python中)它內嵌在Python中,並經過 re 模塊實現。正則表達式模式被編譯成一系列的字節碼,而後由用 C 編寫的匹配引擎執行。

字符匹配(普通字符,元字符):

1 普通字符:大多數字符和字母都會和自身匹配
              >>> re.findall('alvin','yuanaleSxalexwupeiqi')
                      ['alvin'] 

2 元字符:. ^ $ * + ? { } [ ] | ( ) \

元字符之. ^ $ * + ? { }

?
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
import re
 
ret = re.findall( 'a..in' , 'helloalvin' )
print (ret) #['alvin']
 
 
ret = re.findall( '^a...n' , 'alvinhelloawwwn' )
print (ret) #['alvin']
 
 
ret = re.findall( 'a...n$' , 'alvinhelloawwwn' )
print (ret) #['awwwn']
 
 
ret = re.findall( 'a...n$' , 'alvinhelloawwwn' )
print (ret) #['awwwn']
 
 
ret = re.findall( 'abc*' , 'abcccc' ) #貪婪匹配[0,+oo]  
print (ret) #['abcccc']
 
ret = re.findall( 'abc+' , 'abccc' ) #[1,+oo]
print (ret) #['abccc']
 
ret = re.findall( 'abc?' , 'abccc' ) #[0,1]
print (ret) #['abc']
 
 
ret = re.findall( 'abc{1,4}' , 'abccc' )
print (ret) #['abccc'] 貪婪匹配

注意:前面的*,+,?等都是貪婪匹配,也就是儘量匹配,後面加?號使其變成惰性匹配

?
1
2
ret = re.findall( 'abc*?' , 'abcccccc' )
print (ret) #['ab']

元字符之字符集[]:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#--------------------------------------------字符集[]
ret = re.findall( 'a[bc]d' , 'acd' )
print (ret) #['acd']
 
ret = re.findall( '[a-z]' , 'acd' )
print (ret) #['a', 'c', 'd']
 
ret = re.findall( '[.*+]' , 'a.cd+' )
print (ret) #['.', '+']
 
#在字符集裏有功能的符號: - ^ \
 
ret = re.findall( '[1-9]' , '45dha3' )
print (ret) #['4', '5', '3']
 
ret = re.findall( '[^ab]' , '45bdha3' )
print (ret) #['4', '5', 'd', 'h', '3']
 
ret = re.findall( '[\d]' , '45bdha3' )
print (ret) #['4', '5', '3']

元字符之轉義符\

反斜槓後邊跟元字符去除特殊功能,好比\.
反斜槓後邊跟普通字符實現特殊功能,好比\d

\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  匹配一個特殊字符邊界,好比空格 ,&,#等

?
1
2
3
4
ret = re.findall( 'I\b' , 'I am LIST' )
print (ret) #[]
ret = re.findall(r 'I\b' , 'I am LIST' )
print (ret) #['I']

如今咱們聊一聊\,先看下面兩個匹配:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#-----------------------------eg1:
import re
ret = re.findall( 'c\l' , 'abc\le' )
print (ret) #[]
ret = re.findall( 'c\\l' , 'abc\le' )
print (ret) #[]
ret = re.findall( 'c\\\\l' , 'abc\le' )
print (ret) #['c\\l']
ret = re.findall(r 'c\\l' , 'abc\le' )
print (ret) #['c\\l']
 
#-----------------------------eg2:
#之因此選擇\b是由於\b在ASCII表中是有意義的
m = re.findall( '\bblow' , 'blow' )
print (m)
m = re.findall(r '\bblow' , 'blow' )
print (m)

                       

元字符之分組()

?
1
2
3
4
5
6
m = re.findall(r '(ad)+' , 'add' )
print (m)
 
ret = re.search( '(?P<id>\d{2})/(?P<name>\w{3})' , '23/com' )
print (ret.group()) #23/com
print (ret.group( 'id' )) #23

元字符之|

?
1
2
ret = re.search( '(ab)|\d' , 'rabhdg8sd' )
print (ret.group()) #ab

re模塊下的經常使用方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import re
#1
re.findall( 'a' , 'alvin yuan' )    #返回全部知足匹配條件的結果,放在列表裏
#2
re.search( 'a' , 'alvin yuan' ).group()  #函數會在字符串內查找模式匹配,只到找到第一個匹配而後返回一個包含匹配信息的對象,該對象能夠
                                      # 經過調用group()方法獲得匹配的字符串,若是字符串沒有匹配,則返回None。
 
#3
re.match( 'a' , 'abc' ).group()     #同search,不過盡在字符串開始處進行匹配
 
#4
ret = re.split( '[ab]' , 'abcd' )     #先按'a'分割獲得''和'bcd',在對''和'bcd'分別按'b'分割
print (ret) #['', '', 'cd']
 
#5
ret = re.sub( '\d' , 'abc' , 'alvin5yuan6' , 1 )
print (ret) #alvinabcyuan6
ret = re.subn( '\d' , 'abc' , 'alvin5yuan6' )
print (ret) #('alvinabcyuanabc', 2)
 
#6
obj = re. compile ( '\d{3}' )
ret = obj.search( 'abc123eeee' )
print (ret.group()) #123
?
1
2
3
4
5
6
import re
ret = re.finditer( '\d' , 'ds3sy4784a' )
print (ret)        #<callable_iterator object at 0x10195f940>
 
print ( next (ret).group())
print ( next (ret).group())

注意:

?
1
2
3
4
5
6
7
import re
 
ret = re.findall( 'www.(baidu|oldboy).com' , 'www.oldboy.com' )
print (ret) #['oldboy']     這是由於findall會優先把匹配結果組裏內容返回,若是想要匹配結果,取消權限便可
 
ret = re.findall( 'www.(?:baidu|oldboy).com' , 'www.oldboy.com' )
print (ret) #['www.oldboy.com']

補充:

import re

print(re.findall("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>"))
print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>"))
print(re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>"))
View Code

補充2

#匹配出全部的整數
import re

#ret=re.findall(r"\d+{0}]","1-2*(60+(-40.35/5)-(-4*3))")
ret=re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")
ret.remove("")

print(ret)
View Code
相關文章
相關標籤/搜索