python 模塊、包

模塊

模塊導入:

import導入模塊乾的事

1.產生新的名稱空間
2.以新建的名稱空間爲全局名稱空間,執行文件的代碼
3.拿到一個模塊名spam,指向spam.py產生的名稱空間

from .. import ..

1.產生新的名稱空間
2.以新建的名稱空間爲全局名稱空間,執行文件的代碼
3.直接拿到就是spam.py產生的名稱空間中名字

優勢:方便,不用加前綴
缺點:容易跟當前文件的名稱空間衝突

__all__=['money']  #加入spam文件內[ ]內必須是字符串 
from spam import * #*表明all

模塊搜索順序

內存---->內置------->sys.pathnode

若倒入的模塊跟執行的py不在一個路徑下,則用sys.path:python

方法1.
#sys.path.insert更精準
import sys
#sys.path.append(r'/Users/boxfish-edu/PycharmProjects/untitled/d/a')
sys.path.insert(0,r'/Users/boxfish-edu/PycharmProjects/untitled/d/a')
import aaa
print(aaa.name)

方法2.
#a.b表示兩層目錄
from a.b import bbb
print(bbb.name)

正則表達式re模塊

經常使用正則表達式符號

'.'     默認匹配除\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'}

經常使用的匹配語法

re.match 從頭開始匹配
re.search 匹配包含
re.findall 把全部匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符當作列表分隔符
re.sub      匹配字符並替換
print(re.findall('a.c','abc1\nn2a\nc3\tad_efa * | - =',re.S)) #加上re.s可使.匹配\n

print(re.findall('al(?:e)x\smak(?:e)','alex make love'))   #固定語法 不僅僅匹配括號裏的

正則表達式概念

  1. 使用單個字符串來描述匹配一系列符合某個句法規則的字符串
  2. 是對字符串操做的一種邏輯公式
  3. 應用場景:處理文本和數據
  4. 正則表示是過程:依次拿出表達式和文本中的字符比較,若是每個字符都能匹配,則匹配成功;不然匹配失敗

字符匹配

字符 描述
. 匹配任意一個字符(除了\n)
\d \D 數字/非數字
\s \S 空白/非空白字符
\w \W 單詞字符[a-zA-Z0-9]/非單詞字符
\b \B 單詞邊界,一個\w與\W之間的範圍,順序可逆/非單詞邊界
  • 匹配任意一個字符
# 匹配字符串abc,.表明b
 >>> re.match('a.c','abc').group()
'abc'
  • 數字與非數字
# 匹配任意一數字
 >>> re.match('\d','1').group()
'1'
 # 匹配任意一個非數字
 >>> re.match('\D','a').group()
'a'
  • 空白與非空白字符
# 匹配任意一個空白字符
 >>> re.match("\s"," ").group()
' '
 # 匹配任意一個非空白字符
 >>> re.match("\S","1").group()
'1'
 >>> re.match("\S","a").group()
'a'
  • 單詞字符與非單詞字符

單詞字符即表明[a-zA-Z0-9]mysql

# 匹配任意一個單詞字符
 >>> re.match("\w","a").group()
'a'
 >>> re.match("\w","1").group()
'1'
 # 匹配任意一個非單詞字符
 >>> re.match("\W"," ").group()
' '

次數匹配

字符 匹配
* 匹配前一個字符0次或者無限次
+ 匹配前一個字符1次或者無限次
? 匹配前一個字符0次或者1次
{m}/{m,n} 匹配前一個字符m次或者N次
*?/+?/?? 匹配模式變爲貪婪模式(儘量少匹配字符)
  • 介紹
字符 匹配
prev? 0個或1個prev
prev* 0個或多個prev,儘量多地匹配
prev*? 0個或多個prev,儘量少地匹配
prev+ 1個或多個prev,儘量多地匹配
prev+? 1個或多個prev,儘量少地匹配
prev{m} m個連續的prev
prev{m,n} m到n個連續的prev,儘量多地匹配
prev{m,n}? m到n個連續的prev,儘量少地匹配
[abc] a或b或c
[^abc] 非(a或b或c)
  • 匹配前一個字符0次或者無限次
>>> re.match('[A-Z][a-z]*','Aaa').group()
'Aaa'
 >>> re.match('[A-Z][a-z]*','Aa').group()
'Aa'
 >>> re.match('[A-Z][a-z]*','A').group()
'A'
  • 匹配前一個字符1次或者無限次
# 匹配前一個字符至少一次,若是一次都沒有就會報錯
 >>> re.match('[A-Z][a-z]+','A').group()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
>>> re.match('[A-Z][a-z]+','Aa').group()
'Aa'
 >>> re.match('[A-Z][a-z]+','Aaaaaaa').group()
'Aaaaaaa'
  • 匹配前一個字符0次或者1次
>>> re.match('[A-Z][a-z]?','A').group()
'A'
 # 只匹配出一個a
 >>> re.match('[A-Z][a-z]?','Aaaa').group()
'Aa'
  • 匹配前一個字符m次或者N次
#匹配前一個字符至少5次
 >>> re.match('\w{5}','asd234').group()
'asd23'
 # 匹配前面的字符6-10次
 >>> re.match('\w{6,10}','asd234').group()
'asd234'
 # 超過的字符就匹配不出來
 >>> re.match('\w{6,10}','asd2313qeadsd4').group()
'asd2313qea'
  • 匹配模式變爲貪婪模式
>>> re.match(r'[0-9][a-z]*','1bc').group()
'1bc'
 # *?匹配0次或者屢次
 >>> re.match(r'[0-9][a-z]*?','1bc').group()
'1'
 # +?匹配一次或者屢次,可是隻匹配了一次
 >>> re.match(r'[0-9][a-z]+?','1bc').group()
'1b'
 # ??匹配0次或者一次
 >>> re.match(r'[0-9][a-z]??','1bc').group()
'1'

貪婪匹配和非貪婪匹配web

邊界匹配

字符 匹配
^ 匹配字符串開頭
$ 匹配字符串結尾
\A \Z 指定的字符串必須出如今開頭/結尾
  • 匹配字符串開頭
# 必須以指定的字符串開頭,結尾必須是@163.com
 >>> re.match('^[\w]{4,6}@163.com$','asdasd@163.com').group()
'asdasd@163.com'
  • 匹配字符串結尾
# 必須以.me結尾
 >>> re.match('[\w]{1,20}.me$','ansheng.me').group()
'ansheng.me'
  • 指定的字符串必須出如今開頭/結尾
>>> re.match(r'\Awww[\w]*\me','wwwanshengme').group()
'wwwanshengme'

正則表達式分組匹配

  • | 匹配左右任意一個表達式
>>> re.match("www|me","www").group()
'www'
 >>> re.match("www|me","me").group()
'me'
  • (ab) 括號中表達式做爲一個分組
# 匹配163或者126的郵箱
 >>> re.match(r'[\w]{4,6}@(163|126).com','asdasd@163.com').group()
'asdasd@163.com'
 >>> re.match(r'[\w]{4,6}@(163|126).com','asdasd@126.com').group()
'asdasd@126.com'
  • (?P ) 分組起一個別名
>>> re.search("(?P<zimu>abc)(?P<shuzi>123)","abc123").groups()
('abc', '123')
  • 引用別名爲name的分組匹配字符串
>>> res.group("shuzi")
'123'
 >>> res.group("zimu")
'abc'

re模塊經常使用的方法

  • re.match()

語法格式:正則表達式

match(pattern, string, flags=0)

釋意:算法

Try to apply the pattern at the start of the string, returning a match object, or None if no match was found.sql

實例:shell

# 從頭開始匹配,匹配成功則返回匹配的對象
 >>> re.match("abc","abc123def").group()
'abc'
 # 從頭開始匹配,若是沒有匹配到對應的字符串就報錯
 >>> re.match("\d","abc123def").group()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
  • re.search()

語法格式:編程

search(pattern, string, flags=0)

釋意:

Scan through string looking for a match to the pattern, returning a match object, or None if no match was found.

實例:

# 匹配整個字符串,匹配到第一個的時候就返回匹配到的對象
 >>> re.search("\d","abc1123def").group()
'1'
  • re.findall()

語法格式:

findall(pattern, string, flags=0)

釋意:

Return a list of all non-overlapping matches in the string.

實例:

# 匹配字符串全部的內容,把匹配到的字符串以列表的形式返回
 >>> re.findall("\d","abc123def456")
['1', '2', '3', '4', '5', '6']
  • re.split

語法格式:

split(pattern, string, maxsplit=0)

釋意:

Split the source string by the occurrences of the pattern, returning a list containing the resulting substrings.

實例:

# 指定以數字進行分割,返回的是一個列表對象
 >>> re.split("\d+","abc123def4+-*/56")
['abc', 'def', '+-*/', '']
 # 以多個字符進行分割
 >>> re.split("[\d,]","a,b1c")
['a', 'b', 'c']
  • re.sub()

語法格式:

sub(pattern, repl, string, count=0)

釋意:

Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement repl. repl can be either a string or a callable;
if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.

實例:

# 把abc替換成def
 >>> re.sub("abc","def","abc123abc")
'def123def'
 # 只替換查找到的第一個字符串
 >>> re.sub("abc","def","abc123abc",count=1)
'def123abc'

實例

string方法包含了一百個可打印的ASCII字符,大小寫字母、數字、空格以及標點符號

>>> import string
 >>> printable = string.printable
 >>> printable
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
>>> import re
 # 定義的字符串
 >>> source = '''I wish I may, I wish I migth
... Hava a dish of fish tonight.'''
 # 在字符串中檢索wish
 >>> re.findall('wish',source)
['wish', 'wish']
 # 對源字符串任意位置查詢wish或者fish
 >>> re.findall('wish|fish',source)
['wish', 'wish', 'fish']
 # 從字符串開頭開始匹配wish
 >>> re.findall('^wish',source)    
[]
 # 從字符串開頭匹配I wish
 >>> re.findall('^I wish',source)
['I wish']
 # 從字符串結尾匹配fish
 >>> re.findall('fish$',source)   
[]
 # 從字符串結尾匹配fish tonight.
 >>> re.findall('fish tonight.$',source)
['fish tonight.']
 # 查詢以w或f開頭,後面緊跟着ish的匹配
 >>> re.findall('[wf]ish',source)
['wish', 'wish', 'fish']
 # 查詢以若干個w\s\h組合的匹配
 >>> re.findall('[wsh]+',source) 
['w', 'sh', 'w', 'sh', 'h', 'sh', 'sh', 'h']
 # 查詢以ght開頭,後面緊跟着一個非數字和字母的匹配
 >>> re.findall('ght\W',source)
['ght.']
 # 查詢已以I開頭,後面緊跟着wish的匹配
 >>> re.findall('I (?=wish)',source)
['I ', 'I ']
 # 最後查詢以wish結尾,前面爲I的匹配(I出現次數儘可能少)
 >>> re.findall('(?<=I) wish',source)
[' wish', ' wish']
  • 匹配時不區分大小寫
>>> re.match('a','Abc',re.I).group()
'A'
  • r 源字符串,轉義,若是要轉義要加兩個\n
>>> import re
 >>> pa = re.compile(r'ansheng')
 >>> pa.match("ansheng.me")
<_sre.SRE_Match object; span=(0, 7), match='ansheng'>
 >>> ma = pa.match("ansheng.me")
 >>> ma
<_sre.SRE_Match object; span=(0, 7), match='ansheng'>
 # 匹配到的值存到group內
 >>> ma.group()
'ansheng'
 # 返回字符串的全部位置
 >>> ma.span()
(0, 7)
 # 匹配的字符串會被放到string中
 >>> ma.string
'ansheng.me'
 # 實例放在re中
 >>> ma.re
re.compile('ansheng')

time模塊

import time

#時間戳
print(time.time())

#結構化的時間(struct_time):struct_time元組共有9個元素共九個元素:(年,月,日,時,分,秒,一年中第幾周,一年中第幾天,夏令時)
print(time.localtime())     #本地時區的struct_time
print(time.localtime().tm_year)
print(time.gmtime())      #UTC時區的struct_time

#格式化字符串
print(time.strftime('%Y-%m-%d %H:%M:%S'))
print(time.strftime('%Y-%m-%d %X'))

print(time.localtime(123123131))   #將一個時間戳轉換爲當前時區的struct_time

print(time.localtime(time.time()))      #時間戳->結構化時間
print(time.mktime(time.localtime()))    #將一個struct_time轉化爲時間戳。

print(time.strftime('%Y %X',time.localtime()))  #結構化時間->格式化字符串時間
print(time.strptime('2017-06-19 10:41:28','%Y-%m-%d %X'))  #格式化字符串時間->結構化時間

print(time.ctime(123123132))
print(time.asctime(time.localtime()))

random 模塊

import random
print(random.random())  # (0,1)----float    大於0且小於1之間的小數

print(random.randint(1, 3))  # [1,3]  大於等於1且小於等於3之間的整數

print(random.randrange(1, 3))  # [1,3)  大於等於1且小於3之間的整數
print(random.randrange(1, 10,2))

print(random.choice([1, '23', [4, 5]]))  # 1或者23或者[4,5]

print(random.sample([1, '23', [4, 5]], 2))  # 列表元素任意2個組合

print(random.uniform(1, 3))  # 大於1小於3的小數,如1.927109612082716

item = [1, 3, 5, 7, 9]
random.shuffle(item)  # 打亂item的順序,至關於"洗牌"
print(item)

隨機選擇IP

proxy_ip=[
    '1.1.1.1',
    '1.1.1.2',
    '1.1.1.3',
    '1.1.1.4',
]
print(random.choice(proxy_ip))

生成驗證碼

def v_code(n=5):
    res= ''
    for i in range(n):
        a = random.randint(0,9)
        b = chr(random.randint(65,90))
        c = random.choice([a,b])
        res +=str(c)
    return res

a = v_code(5)
print(a)

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所指向的文件或者目錄的最後修改時間
os.path.getsize(path) 返回path的大小
在Linux和Mac平臺上,該函數會原樣返回path,在windows平臺上會將路徑中全部字符轉換爲小寫,並將全部斜槓轉換爲飯斜槓。
>>> os.path.normcase('c:/windows\\system32\\')   
'c:\\windows\\system32\\'   
   

規範化路徑,如..和/
>>> os.path.normpath('c://windows\\System32\\../Temp/')   
'c:\\windows\\Temp'   

>>> a='/Users/jieli/test1/\\\a1/\\\\aa.py/../..'
>>> print(os.path.normpath(a))
/Users/jieli/test1
os路徑處理
#方式一:推薦使用
import os
#具體應用
import os,sys
possible_topdir = os.path.normpath(os.path.join(
    os.path.abspath(__file__),
    os.pardir, #上一級
    os.pardir,
    os.pardir
))
sys.path.insert(0,possible_topdir)


#方式二:不推薦使用
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

sys模塊

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(50):
    sys.stdout.write('%s\r' %('#'*i))   #\r將光標移動到首行
    sys.stdout.flush()
    time.sleep(0.1)

'''
注意:在pycharm中執行無效,請到命令行中以腳本的方式執行
'''

shutil模塊

高級的 文件、文件夾、壓縮包 處理模塊

將文件內容拷貝到另外一個文件中

import shutil
shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))

拷貝文件

shutil.copyfile('f1.log', 'f2.log') #目標文件無需存在

僅拷貝權限。內容、組、用戶均不變

shutil.copymode('f1.log', 'f2.log') #目標文件必須存在

僅拷貝狀態的信息,包括:mode bits, atime, mtime, flags

shutil.copystat('f1.log', 'f2.log') #目標文件必須存在

拷貝文件和權限

import shutil
shutil.copy('f1.log', 'f2.log')

拷貝文件和狀態信息

import shutil
shutil.copy2('f1.log', 'f2.log')

shutil 對壓縮包的處理是調用 ZipFile 和 TarFile 兩個模塊來進行的,詳細:

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()

zipfile壓縮解壓縮
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()

tarfile壓縮解壓縮

json 模塊

import json
#序列化的過程:dic--->res=json.dups(dic)--->f.write(res)
dic={
    'name':'alex',
    'age':9000,
    'height':'150cm',
}
with open('a.json','w') as f:
    res = json.dumps(dic)
    print(res, type(res))
    f.write(res)

#反序列化的過程:dic =f.read()---> res = json.loads(res)--->dic=res
with open('a.json','r') as f:
    res = f.read()
    dic = json.loads(res)
    print(dic,type(dic))
    print(dic['name'])

#json的便捷操做
json.dump(dic,open('b.json','w'))

res = json.load(open('b.json','r'))
print(res)

pickle 模塊

import pickle
dic={'name':'alex','age':13}
print(pickle.dumps(dic))
with open('a.pkl','wb') as f:
    f.write(pickle.dumps(dic))

with open('a.pkl','rb') as f:
    d = pickle.loads(f.read())
    print(d,type(d))

pickle.dump(dic,open('b.pkl','wb'))
res = pickle.load(open('b.pkl','rb'))
print(res)

import json
import pickle
def func():
    print('from func')

#json.dumps(func)# 報錯,json不支持python的函數類型
f=pickle.dumps(func)
print(f)

pickle.dump(func,open('c.pkl','wb'))
res=pickle.load(open('c.pkl','rb'))
print(res)
res()

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


shelve模塊

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

import shelve
f=shelve.open(r'sheve.txt')
f['student1']={'name':'egon','age':18,'height':'180cm'}
print(f['student1']['name'])
f.close()

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操做:

#!/usr/bin/python
# -*- coding:utf-8 -*-

import xml.etree.ElementTree as ET

tree = ET.parse("a")
root = tree.getroot()

print(root.iter('year'))        #全文搜索
print(root.find('country'))     #在root的子節點找,只找一個
print(root.findall('country'))  #在root的子節點找,找全部


for country in root:
    print('=====>',country.attrib['name'])
    for item in country:
        print(item.tag,item.text,item.attrib)

for year in root.iter('year'):
    print(year.tag,year.text,year.attrib)   #tag,text,attrib 分別描述不一樣的內容


#修改
for year in root.iter('year'):
    print(year.text)
    year.text=str(int(year.text)+1)
    print(year.attrib)
    year.set('update','yes')


tree.write('b.xml')     #建立並修改文件
tree.write('a')         #更改當前文件


for country in root:
    print(country)
    print('===>',country.find('year'))
    year=country.find('year')
    if int(year.text) > 2010:
        country.remove(year)

tree.write('d.xml')


#增長
for country in root:
    print(country)
    # print('===>',country.find('year'))
    year=country.find('year')
    if int(year.text) > 2010:
        year2 = ET.Element('year2')
        year2.text=str(int(year.text)+1)
        year2.set('update','yes')
        country.append(year2)
tree.write('e.xml')


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

參考

Python標準庫系列之xml模塊

Python’s interfaces for processing XML are grouped in the xml package.

帶分隔符的文件僅有兩維的數據:行和列。若是你想在程序之間交換數據結構,須要一種方法把層次結構、序列、集合和其餘的結構編碼成文本。

XML是最突出的處理這種轉換的標記(markup)格式,它使用標籤(tag)分個數據,以下面的實例文件menu.xml所示:

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>安生&#39;s Blog</title>
  <subtitle>大好時光!</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://blog.ansheng.me/"/>
  <updated>2016-05-24T15:29:19.000Z</updated>
  <id>https://blog.ansheng.me/</id>
  
  <author>
    <name>安生</name>
  </author>
</feed>

XML的一些重要特性

  1. 標籤以一個<字符開頭,例如實例中的feed、title、subtitle、author。
  2. 忽略空格
  3. 一般一個開始標籤跟一段其餘的內容,而後是最後相匹配的結束標籤,例如 大好時光!
  4. 標籤之間是能夠存在多級嵌套的
  5. 可選屬性(attribute)能夠出如今開始標籤裏
  6. 標籤中能夠包含值(value)
  7. 若是一個命名爲thing的標籤內沒有內容或者子標籤,那麼它能夠用在右尖括號的前面添加斜槓的簡單標籤所表示,例如 代替開始和結束都存在的標籤。
  8. 存放數據的位置能夠是任意的---屬性、值或者子標籤。

XML一般用於數據傳送和消息,它存在一些子格式,如RSS和Atom,例如:https://blog.ansheng.me/atom.xml

在Python中解析XML最簡單的方法是使用ElementTree

模塊 說明
xml.etree.ElementTree the ElementTree API, a simple and lightweight XML processor

建立xml文件

導入ElementTree方法,起一個別名爲ET

>>> from xml.etree import ElementTree as ET

建立頂級標籤

>>> level_1 = ET.Element("famliy")

建立二級標籤,tag名name,attrib標籤屬性

>>> level_2 = ET.SubElement(level_1, "name", attrib={"enrolled":"yes"})

建立三級標籤

>>> level_3 = ET.SubElement(level_2, "age", attrib={"checked":"no"})

生成文檔

>>> tree = ET.ElementTree(level_1)

寫入文件中

>>> tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False)

導入os模塊,用os模塊中的system方法執行shell命令查看剛纔建立的oooo.xml文件

>>> import os
>>> os.system("cat oooo.xml")
# 生成出來的文檔是沒有換行的
<famliy><name enrolled="yes"><age checked="no"></age></name></famliy>0

把剛纔生成的文件下載到本地,而後用瀏覽器打開就能夠看到分級層次了。

建立一個有換行的XML文件

代碼

from xml.etree import ElementTree as ET
from xml.dom import minidom

root = ET.Element('level1',{"age":"1"})
son = ET.SubElement(root,"level2",{"age":"2"})
ET.SubElement(son, "level3", {"age":"3"})

# tree = ET.ElementTree(root)
# tree.write("abc.xml", encoding="utf-8",xml_declaration=True,short_empty_elements=False)

def prettify(root):
    rough_string = ET.tostring(root, 'utf-8')
    reparsed = minidom.parseString(rough_string)
    return reparsed.toprettyxml(indent="\t")

new_str = prettify(root)
f = open("new_out.xml", "w")
f.write(new_str)
f.close()

生成的xml文件

<?xml version="1.0" ?>
<level1 age="1">
    <level2 age="2">
        <level3 age="3"/>
    </level2>
</level1>

解析XML

first.xml文件內容爲:

<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year age="19">2025</year>
        <gdppc>141100</gdppc>
        <neighbor direction="E" name="Austria" />
        <neighbor direction="W" name="Switzerland" />
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year age="19">2028</year>
        <gdppc>59900</gdppc>
        <neighbor direction="N" name="Malaysia" />
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year age="19">2028</year>
        <gdppc>13600</gdppc>
        <neighbor direction="W" name="Costa Rica" />
        <neighbor direction="E" name="Colombia" />
    </country>
</data>

first.xml文件在/root目錄下

利用ElementTree.XML將字符串解析成xml對象

>>> from xml.etree import ElementTree as ET
# 打開文件,讀取XML內容,將字符串解析成xml特殊對象,root代指xml文件的根節點 
>>> root = ET.XML(open('first.xml', 'r').read())
>>> root.tag
'data'
>>> for node in root:
...  print(node.tag, node.attrib)
... 
('country', {'name': 'Liechtenstein'})
('country', {'name': 'Singapore'})
('country', {'name': 'Panama'})
>>> print(node.find('rank').text)
69

利用ElementTree.parse將文件直接解析成xml對象

>>> from xml.etree import ElementTree as ET
# 直接解析xml文件
>>> tree = ET.parse("first.xml")
# 獲取xml文件的根節點
>>> root = tree.getroot()
>>> root.tag
'data'

遍歷XML中指定的節點

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot()
>>> for node in root.iter('year'):
        # 輸出node的tag和內容
...     print(node.tag, node.text)
...
year 2025
year 2028
year 2028

增、刪、改XML

爲節點添加屬性

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot()
>>> for node in root.iter("year"):
        # 查看原來的屬性
...     print(node.attrib)
...
{}
{}
{}
>>> for node in root.iter("year"):
       # 添加屬性
...    node.set("OS","Linux")
...
>>> for node in root.iter("year"):
        # 查看添加的屬性
...     print(node.attrib) 
...
{'OS': 'Linux'}
{'OS': 'Linux'}
{'OS': 'Linux'}
# 把內容寫入文件
>>> tree.write("first.xml")

刪除節點屬性

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot()
>>> for node in root.iter("year"):
        # 刪除節點的OS屬性
...     del node.attrib['OS']
...
# 寫入到文件當中
>>> tree.write("first.xml")

查看屬性

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot()
>>> for node in root.iter("year"):
...  print(node.attrib)
...
# 節點內容爲空
{}
{}
{}

修改節點內容

修改year內的數字自加1

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot() 
>>> for node in root.iter("year"):
        # 輸出原來year的內容
...     print(node.text)
        # 原來的值自加+
...     new_year = int(node.text) + 1
...     node.text = str(new_year)
...
2025
2028
2028 
# 寫入文件中
>>> tree.write("first.xml")
>>> for node in root.iter("year"):
        # 輸出寫入文件以後year的內容
...     print(node.text)
...
2026
2029
2029

對節點操做的方法

獲取節點的方法

>>> from xml.etree import ElementTree as ET
>>> tree = ET.parse("first.xml")
>>> root = tree.getroot()
>>> print(dir(root))
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'extend', 'find', 'findall', 'findtext', 'get', 'getchildren', 'getiterator', 'insert', 'items', 'iter', 'iterfind', 'itertext', 'keys', 'makeelement', 'remove', 'set']

方法有這麼多,那麼咱們經常使用的也就是下面的幾個

方法名 說明
tag 獲取tag標籤名
attrib 獲取節點的屬性
find 獲取節點的內容
iter 進行迭代
set 設置屬性
get 獲取屬性

實例

判斷QQ是否在線

騰訊提供了可以查看QQ號碼是否在線的API,Y=在線;N=離線;E=QQ號碼錯誤;A=商業用戶驗證失敗;V=免費用戶超過數量

>>> import requests
>>> from xml.etree import ElementTree as ET
>>> r = requests.get("http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=6087414")
>>> result = r.text
>>> from xml.etree import ElementTree as ET
>>> node = ET.XML(result)
>>> if node.text == "Y":
...    print("在線")
... else:
...    print("離線")
...
在線

獲取列車起止時間

代碼

r = requests.get("http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=K234&UserID=")
result = r.text
root = ET.XML(result)
for node in root.iter('TrainDetailInfo'):
    print(node.find('TrainStation').text,node.find('ArriveTime').text,node.find("StartTime").text)

執行結果

C:\Python35\python.exe F:/Python_code/sublime/Week5/Day01/xml_mod.py
上海(車次:K234\K235) None 11:12:00
# 地點 中止    啓動
崑山 11:45:00 11:48:00
蘇州 12:12:00 12:16:00
無錫 12:44:00 12:55:00
常州 13:22:00 13:26:00
鎮江 14:13:00 14:16:00
南京 15:04:00 15:16:00
蚌埠 17:27:00 17:50:00
徐州 19:38:00 19:58:00
商丘 22:12:00 22:17:00
開封 23:49:00 23:53:00
鄭州 00:37:00 01:14:00
新鄉 02:20:00 02:22:00
鶴壁 03:01:00 03:03:00
安陽 03:33:00 03:36:00
邯鄲 04:11:00 04:16:00
邢臺 04:47:00 04:51:00
石家莊 06:05:00 None

Process finished with exit code 0

hashlib 模塊

This module implements a common interface to many different secure hash and message digest algorithms. Included are the FIPS secure hash algorithms SHA1, SHA224, SHA256, SHA384, and SHA512 (defined in FIPS 180-2) as well as RSA’s MD5 algorithm (defined in Internet RFC 1321). The terms 「secure hash」 and 「message digest」 are interchangeable. Older algorithms were called message digests. The modern term is secure hash.

官方文檔:https://docs.python.org/3.5/library/hashlib.html

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

md5加密

>>> import hashlib
m = hashlib.md5()
m.update('me'.encode('utf-8'))
print(m.hexdigest())

m = hashlib.md5()
with open('a','rb') as f:
    for i in f:
        m.update(i)
    md5_num = m.hexdigest()
print(md5_num)

sha1

>>> import hashlib
>>> hash = hashlib.sha1()
>>> hash.update(bytes('ansheng', encoding='utf-8'))
>>> hash.hexdigest()
'd1dec3927fbe94ace7f7ebe6c53a844e0265455a'

sha256

import hashlib
s = hashlib.sha256()
s.update('helloword'.encode('utf-8'))
print(s.hexdigest())

sha384

>>> import hashlib
>>> hash = hashlib.sha384()
>>> hash.update(bytes('ansheng', encoding='utf-8'))
>>> hash.hexdigest()
'01cab50e3cc7801fec2988573ad62a645daf636a6d2a47d41c7a456113bee6e657a3ff367029f617e38a03d732c8113d'

sha512

>>> import hashlib
>>> hash = hashlib.sha512()
>>> hash.update(bytes('ansheng', encoding='utf-8'))
>>> hash.hexdigest()
'79cc48a191152112bd8285979784fc4bba9b0f2d5ac26f96de1ec87a6fbf4935dcb3ba9bc027c3791875b96dd725e01863602f59d4a561bbd2823495cd4553fc'

撞庫實例:

import hashlib
passwds=[
    'alex3714',
    'alex1313',
    'alex94139413',
    'alex123456',
    '123456alex',
    'a123lex',
    ]

def make_pass_dic(passwords):
    dic = {}
    m = hashlib.md5()
    for passwd in passwds:
        m.update(passwd.encode('utf-8'))
        dic[passwd] = m.hexdigest()
    return dic


def break_code(cryptograph,dic_passwd):
    for k,v in dic_passwd.items():
        if v == cryptograph:
            print('密碼是--->',k)


cryptograph = 'aee949757a2e698417463d47acac93df'
break_code(cryptograph,make_pass_dic(passwds))

爲防止別人對咱們的md5值進行撞庫,咱們能夠給md5加個鹽

import hashlib
m=hashlib.md5('yihangbailushangqingtian'.encode('utf-8'))
m.update('alex3714'.encode('utf-8'))
print(m.hexdigest())

另一個加鹽的模塊

import hmac
h = hmac.new('egon123456'.encode('utf-8'))
h.update('alex3714'.encode('utf-8'))
print(h.hexdigest())

實例

根據用戶輸入的登陸名和口令模擬用戶註冊,計算更安全的MD5:
而後,根據修改後的MD5算法實現用戶登陸的驗證.

import hashlib
db = {}
def calc_md5(password):
    md5 = hashlib.md5()
    md5.update(password.encode())
    return md5.hexdigest()

def register(user,password):
    db[user] = calc_md5(password + user + 'the-Salt')

def login(user,password):
    p = calc_md5(password + user + 'the-Salt')
    if user in db:
        if db[user] == p:
            print('login successful')
        else:
            print('wrong')
    else:
        print('can not find',username)

while True:
    x = input('register:1 login:2 quit:0\n')
    if x == '0':
        break
    elif x == '1':
        user = input('input your name:\n')
        password = input('input your password:\n')
        register(user, password)

    elif x == '2':
        user = input('input your name:\n')
        password = input('input your password:\n')
        login(user, password)
    else:
        print('wrong')

subprocess 模塊

import subprocess
res = subprocess.Popen('ls',shell=True,stdout=subprocess.PIPE)
print(res)
print(res.stdout.read().decode('gbk'))


#stderr 能夠在出錯是不報錯
res = subprocess.Popen('diasd',shell=True,
                       stderr = subprocess.PIPE,
                       stdout = subprocess.PIPE
                       )

print('---->',res.stdout.read())
print('---->',res.stderr.read().decode('gbk'))


res1 = subprocess.Popen(r'ls /Users/boxfish-edu/PycharmProjects/untitled/e',shell=True,stdout=subprocess.PIPE)
#print(res1.stdout.read())
res=subprocess.Popen(r'ls test*',shell=True,
                     stdin=res1.stdout,
                     stderr=subprocess.PIPE,
                     stdout=subprocess.PIPE)

print('===>',res.stdout.read().decode('gbk'))#管道取一次就空了
print('===>',res.stdout.read().decode('gbk'))#管道取一次就空了

官網介紹:

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

經常使用方法實例

call()

執行命令,並返回狀態碼,狀態碼0表明命令執行成功,其餘的都表示命令執行不成功

>>> ret = subprocess.call(["ls", "-l"], shell=False)
total 4
-rw-r--r-- 1 root root 172 May 25 21:21 file.conf
>>> ret
0

另外一種執行方式

# shell=True表示調用原生的shell命令去執行
>>> ret = subprocess.call("ls -l", shell=True)
total 4
-rw-r--r-- 1 root root 172 May 25 21:21 file.conf
>>> ret
0

check_call()

執行命令,若是執行狀態碼是0,則返回0,不然拋異常

# 執行一個正確的命令就會返回執行結果和狀態碼
>>> subprocess.check_call(["ls", "-l"])
total 4
-rw-r--r-- 1 root root 172 May 25 21:21 file.conf
0
# 若是執行的是一個錯誤的命令,那麼就會返回錯誤信息
>>> subprocess.check_call(["ls", "a"])  
ls: cannot access a: No such file or directory
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/subprocess.py", line 505, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['ls', 'a']' returned non-zero exit status 2

check_output()

執行命令,若是狀態碼是0,則返回執行結果,不然拋異常

# 執行成功就把執行的結果賦值給變量V
>>> V = subprocess.check_output("python -V", shell=True)
# 執行錯誤的命令就會輸出異常
>>> subprocess.check_output("pasas", shell=True)
'pasas' 不是內部或外部命令,也不是可運行的程序
或批處理文件。
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python35\lib\subprocess.py", line 629, in check_output
    **kwargs).stdout
  File "C:\Python35\lib\subprocess.py", line 711, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'pasas' returned non-zero exit status 1

以上的三種執行方式在執行命令的時候,shell默認等於True,等於True的時候,括號內的命令是一行的,若是shell等於False,那麼[]內的字符串就是命令的一個元素,執行的時候會把[]內的字符串拼接起來執行。

subprocess.Popen()

call()check_call()check_output()默認內部調用的都是subprocess.Popen(),而subprocess.Popen()則用於執行更復雜的系統命令。

參數

參數 說明
stdin 標準輸入
stdout 標準輸出
stderr 錯誤句柄
cwd 用於設置子進程的當前目錄
env 用於指定子進程的環境變量。若是env = None,子進程的環境變量將從父進程中繼承

執行普通命令

>>> subprocess.Popen("Python -V", shell=True)
<subprocess.Popen object at 0x0000025C97233C88>
# Python 3.5.1是輸出出來的結果
>>> Python 3.5.1

執行命令分爲兩種:

  1. 輸入便可獲得輸出,如:ifconfig
  2. 輸入進行某交互式環境,依賴再輸入,如:python
>>> import subprocess
# 先進入'/tmp'目錄,而後在建立subprocess文件夾,shell=True無關緊要
>>> subprocess.Popen("mkdir subprocess", shell=True, cwd='/tmp',)
<subprocess.Popen object at 0x7f267cc3d390>
>>> import os
>>> os.system("ls /tmp")
subprocess

subprocess.Popen()實例

# 導入subprocess模塊
import subprocess

# 執行python命令,進入python解釋器,stdin標準輸入、stdout標準輸出、stderr錯誤輸出,universal_newlines=True自動輸入換行符
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)

# 執行標準輸入,write後面是輸入的命令
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")
# 輸入以後關閉
obj.stdin.close()

# 讀取標準輸出的內容,賦值給cmd_out對象
cmd_out = obj.stdout.read()
# 關閉標準輸出
obj.stdout.close()

# 讀取錯誤輸出的內容,賦值給cmd_error對象
cmd_error = obj.stderr.read()

# 關閉錯誤輸出
obj.stderr.close()

# 輸出內容
print(cmd_out)
print(cmd_error)

執行結果

C:\Python35\python.exe F:/Python_code/sublime/Week5/Day02/sub.py
1
2



Process finished with exit code 0
# 導入subprocess模塊
import subprocess

# 執行python命令,進入python解釋器,stdin標準輸入、stdout標準輸出、stderr錯誤輸出,universal_newlines=True自動輸入換行符
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)

# 執行兩條命令
obj.stdin.write("print(1)\n")
obj.stdin.write("print(2)")

# communicate把錯誤輸出或者標準輸出的內容賦值給out_error_list對象,若是有錯誤就賦值錯誤輸出,不然就複製標準輸出
out_error_list = obj.communicate()

# 輸出out_error_list對象的內容
print(out_error_list)

執行結果

C:\Python35\python.exe F:/Python_code/sublime/Week5/Day02/sub.py
('1\n2\n', '')

Process finished with exit code 0
# 導入subprocess模塊
import subprocess

# 執行python命令,進入python解釋器,stdin標準輸入、stdout標準輸出、stderr錯誤輸出,universal_newlines=True自動輸入換行符
obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)


# 直接執行print("hello")命令,而後把錯誤或者正確的結果賦值給out_error_list對象
out_error_list = obj.communicate('print("hello")')

# 輸出out_error_list對象的內容
print(out_error_list)

執行結果

C:\Python35\python.exe F:/Python_code/sublime/Week5/Day02/sub.py
('hello\n', '')

Process finished with exit code 0

logging日誌模塊

This module defines functions and classes which implement a flexible event logging system for applications and libraries.

The key benefit of having the logging API provided by a standard library module is that all Python modules can participate in logging, so your application log can include your own messages integrated with messages from third-party modules.

官方文檔:https://docs.python.org/3.5/library/logging.html

logging模塊用於便捷記錄日誌且線程安全。

日誌級別

Level Numeric value
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0

只有大於當前日誌等級的操做纔會被記錄。

寫入單文件

代碼

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
# 導入logging模塊
import logging

# 建立一個log.log日誌文件
logging.basicConfig(filename='log.log',
                    # 格式化的字符串
                    format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
                    # 時間
                    datefmt='%Y-%m-%d %H:%M:%S %p',
                    # 錯誤級別
                    level=logging.NOTSET
                    )

logging.critical('critical')
logging.error('error')
logging.warning('warning')
logging.info('info')
logging.debug('debug')
logging.log(logging.INFO, 'NOTSET')

執行結果

ansheng@ansheng-me:~$ ls 
log.py
ansheng@ansheng-me:~$ python log.py 
ansheng@ansheng-me:~$ ls
log.log  log.py
ansheng@ansheng-me:~$ cat log.log 
2016-05-27 21:46:15 PM - root - CRITICAL - log: critical
2016-05-27 21:46:15 PM - root - ERROR - log: error
2016-05-27 21:46:15 PM - root - WARNING - log: warning
2016-05-27 21:46:15 PM - root - INFO - log: info
2016-05-27 21:46:15 PM - root - DEBUG - log: debug
2016-05-27 21:46:15 PM - root - INFO - log: NOTSET

logging.basicConfig函數各參數

參數 說明
filename 指定日誌文件名
filemode 和file函數意義相同,指定日誌文件的打開模式,'w'或'a'
format 指定輸出的格式和內容,format能夠輸出不少有用信息,以下所示
datefmt 指定時間格式,同time.strftime()
level 設置日誌級別,默認爲logging.WARNING

format參數

參數 說明
%(levelno)s 打印日誌級別的數值
%(levelname)s 打印日誌級別名稱
%(pathname)s 打印當前執行程序的路徑,其實就是sys.argv[0]
%(filename)s 打印當前執行程序名
%(funcName)s 打印日誌的當前函數
%(lineno)d 打印日誌的當前行號
%(asctime)s 打印日誌的時間
%(thread)d 打印線程ID
%(threadName)s 打印線程名稱
%(process)d 打印進程ID
%(message)s 打印日誌信息

多文件日誌

對於上述記錄日誌的功能,只能將日誌記錄在單文件中,若是想要設置多個日誌文件,logging.basicConfig將沒法完成,須要自定義文件和日誌操做對象。

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

import logging

# 建立文件
file_1 = logging.FileHandler("log1.log", "a")
# 建立寫入的日誌格式
fmt1 = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s - %(module)s : %(message)s")
# 文件用格式
file_1.setFormatter(fmt1)

file_2 = logging.FileHandler("log2.log", "a")
fmt2 = logging.Formatter()
file_2.setFormatter(fmt2)

logger1 = logging.Logger("s1", level=logging.ERROR)
logger1.addHandler(file_1)
logger1.addHandler(file_2)

logger1.critical("1111")
# 定義文件
file_2_1 = logging.FileHandler('l2_1.log', 'a')
fmt = logging.Formatter()
file_2_1.setFormatter(fmt)

# 定義日誌
logger2 = logging.Logger('s2', level=logging.INFO)
logger2.addHandler(file_2_1)

如上述建立的兩個日誌對象

  1. 當使用logger1寫日誌時,會將相應的內容寫入 l1_1.log 和 l1_2.log 文件中
  2. 當使用logger2寫日誌時,會將相應的內容寫入 l2_1.log 文件中

configparser模塊

This module provides the ConfigParser class which implements a basic configuration language which provides a structure similar to what’s found in Microsoft Windows INI files. You can use this to write Python programs which can be customized by end users easily.

configparser用於處理特定格式的文件,其本質上是利用open來操做文件。

配置文件格式以下:

# 第一種註釋方式
; 第二種註釋方式
 
[node1]  # 節點
k1 = v1  # key = value
k2 : v2  # key : value

實例

import configparser

#爲文件添加節點
config=configparser.ConfigParser()
config.read('a.ini',encoding='utf-8')

config.add_section('node1')
config.add_section('node2')
config.write(open('a.ini','w'))

#檢查節點是否存在
print(config.has_section('node1'))      #存在返回True

#刪除節點
config.remove_section('node2')
config.write(open('a.ini','w'))

#設置節點內的鍵值對
config.set('node1','name','ansheng')
config.set('node1', 'Blog_URL', "https://blog.ansheng.me")
config.set('node1', 'Hostname', "localhost.localhost")
config.set('node1', 'IP', "127.0.0.1")
config.write(open('a.ini', 'w'))

#檢查節點內的key是否存在
#若是節點的Key存在就返回"True",不然返回"False"
print(config.has_option('node1', 'Name'))


#刪除節點內的key

#若是刪除的節點存在就返回"True",不然就返回"False"
print(config.remove_option('node1', 'IP'))


#獲取指定節點下指定key的值
print(config.get('node1','name'))
#返回的字符串咱們能夠設置成一下三種數據類型,分別是"int","float","bool"
v = config.getint('node1', 'name')
v = config.getfloat('node1', 'k1')
v = config.getboolean('node1', 'k1')

#獲取指定節點下全部的key
#返回節點下面全部的Key列表
print(config.options('node1'))

#獲取指定節點下全部的鍵值對
#返回一個列表,列表中每一個元組就是一個鍵值對
print(config.items('node1'))

#獲取全部節點
#獲取當前文件中有多少個節點
print(config.sections())

itertools 模塊

datetime\traceback模塊

json\pickle\xml\yaml\configparser 處理模




包的導入方式

執行文件都是test.py
1.
import glance.api.policy.get #報錯,點的左邊必須是包
import glance.api.policy
glance.api.policy.get()

2.
from glance.api import policy,versions
from glance.cmd import manage
from glance.db import models

policy.get()
manage.main()
models.register_models('mysql')
---
#注意與本文件內函數名之間的衝突
from glance.api.policy import get
from glance.api.versions import create_resource
from glance.cmd.manage import main
from glance.db.models import register_models
get()
create_resource('mysql')
main()
register_models('mysql')


3.
#前提在api下的__init__.py內加入__all__=['policy','versions']
from glance.api import *
policy.get()
print(policy)
print(versions)

4.
#前提在glance下的__init__py配置
from .api import *  #policy,versions
from .cmd import *  #mange
from .db import *   #models

#test.py
import glance
glance.policy.get()
glance.versions.create_resource('mysql')


備註:
import glance
print(glance)
直接倒入glace打印的是glace下的__init__.py

實例目錄結構:
包能夠是結構更清晰,便於開發者修改
'''
---glance
   |
   --api
        |
        ---__init__py
        ---policy.py
        ---versions.py
   --cmd
        |
        ---__init__.py
        ---manage.py
   --db
        |
        ---__init__.py
        ---models.py
   __init__.py
'''
相關文章
相關標籤/搜索