時間模塊 time datatimehtml
time.clock(2.7)node time.process_time(3.3)python |
測量處理器運算時間,不包括sleep時間git |
|
time.altzone正則表達式 |
返回與UTC時間的時間差,以秒計算shell |
print(time.altzone) -32400json |
time.asctime()python3.x |
將struct時間格式轉爲可讀的時間格式"Fri Aug 19 11:14:16 2016"安全 |
print(time.asctime()) 輸出: Mon Jan 2 15:59:48 2017 |
time.localtime() |
輸入時間戳,轉爲本地時區的stuct時間格式 |
stuct時間能夠被調用 t = time.localtime() print(t.tm_year) 輸出: 2017 |
time.gmtime(time.time()-800000) |
輸入時間戳,轉爲UTC時間的stuct時間格式
|
print(time.gmtime(time.time())) |
time.ctime() |
返回 "Fri Aug 19 11:14:16 2016" |
print((time.ctime())) |
日期字符串轉時間戳
time.strptime("str","fomat") |
將字符串轉爲struct時間格式 |
s=time.strptime("2017-1-2","%Y-%m-%d") print(s)
time.struct_time(tm_year=2017, tm_mon=1, tm_mday=2, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=2, tm_isdst=-1) |
time.mktime(struct) |
將struct時間格式轉爲時間戳 |
s=time.strptime("2017-1-2","%Y-%m-%d") # 將字符串轉爲struct時間 print(time.mktime(s))
輸出
1483286400.0 |
time.strftime(format,struct) |
將struct時間格式轉爲字符串 |
t1=time.strftime("%Y-%m-%d%H:%M:%S.log",time.localtime(time.time())) print(t1)
2017-01-02 23:01:01.log |
time.time >> gmtime or localtime >> asctime
時間戳 時間戳轉struct struct轉可讀
time.time >> gmtime or localtime >> strftime
時間戳 時間戳轉struct struct轉自定義可讀
stf >> strptime >> mktime
字符串 字符串轉struct struct轉時間戳
struct_time時間格式
索引 |
屬性 |
值 |
0 |
tm_year(年) |
好比2011 |
1 |
tm_mon(月) |
1 - 12 |
2 |
tm_mday(日) |
1 - 31 |
3 |
tm_hour(時) |
0 - 23 |
4 |
tm_min(分) |
0 - 59 |
5 |
tm_sec(秒) |
0 - 61 |
6 |
tm_wday(weekday) |
0 - 6(0表示週日) |
7 |
tm_yday(一年中的第幾天) |
1 - 366 |
8 |
tm_isdst(是不是夏令時) |
默認爲-1 |
源文檔 <http://www.cnblogs.com/qq78292959/archive/2013/03/22/2975786.html>
格式 |
含義 |
備註 |
%a |
本地(locale)簡化星期名稱 |
|
%A |
本地完整星期名稱 |
|
%b |
本地簡化月份名稱 |
|
%B |
本地完整月份名稱 |
|
%c |
本地相應的日期和時間表示 |
|
%d |
一個月中的第幾天(01 - 31) |
|
%H |
一天中的第幾個小時(24小時制,00 - 23) |
|
%I |
第幾個小時(12小時制,01 - 12) |
|
%j |
一年中的第幾天(001 - 366) |
|
%m |
月份(01 - 12) |
|
%M |
分鐘數(00 - 59) |
|
%p |
本地am或者pm的相應符 |
一 |
%S |
秒(01 - 61) |
二 |
%U |
一年中的星期數。(00 - 53星期天是一個星期的開始。)第一個星期天以前的全部天數都放在第0周。 |
三 |
%w |
一個星期中的第幾天(0 - 6,0是星期天) |
三 |
%W |
和%U基本相同,不一樣的是%W以星期一爲一個星期的開始。 |
|
%x |
本地相應日期 |
|
%X |
本地相應時間 |
|
%y |
去掉世紀的年份(00 - 99) |
|
%Y |
完整的年份 |
|
%Z |
時區的名字(若是不存在爲空字符) |
|
%% |
‘%’字符 |
|
源文檔 <http://www.cnblogs.com/qq78292959/archive/2013/03/22/2975786.html>
datetime
datetime.datetime.now() |
打印當前本地時間 |
t2=datetime.datetime.now() print(t2)
2017-01-02 23:08:52.325153 |
|
datetime.datetime.fromtimestamp() |
時間戳轉成日期格式,所以能夠在裏面對時間戳進行時間運算 |
print(datetime.datetime.fromtimestamp(time.time())) 輸出
2017-01-03 22:23:48.811628 |
|
datetime.timedelta() |
用來時間運算,括號裏面能夠指定多種參數
days=0,seconds=0,microseconds=0, milliseconds=0,minutes=0,hours=0,weeks=0
|
print(datetime.datetime.now()) print(datetime.datetime.now()+datetime.timedelta(days=10))
2017-01-03 22:29:24.129807 2017-01-13 22:29:24.129807
|
|
時間.replace() |
直接替換時間中的年月日等信息
year=None,month=None,day=None,hour=None, minute=None,second=None,microsecond=None,tzinfo=True
|
now=datetime.datetime.now() print(now) print(now.replace(year=2018,month=6,day=8))
2017-01-03 22:35:19.673142 2018-06-08 22:35:19.673142
|
|
隨機數 模塊 random
random.random() |
隨機打印一個小數 |
|
random.randint(1,2) |
隨機生成從1到2的數,即大於等於1小於等於2 |
|
random.randrange(1,10) |
隨機生成從1到9的數,即不包含大於等於1小於10 |
|
random.sample(列表或字符串,數量) |
根據列表或字符串中的元素隨機選擇指定的數量,隨機驗證碼可使用這個方法。前面的取值範圍可使用range(100)取100之內的數字 |
|
String模塊
string.ascii_lowercase |
打印所有ascii編碼中的小寫字母 |
print(string.ascii_lowercase) 輸出 |
string.ascii_uppercase |
打印所有大寫字母 |
|
string.ascii_letters |
打印所有大小寫字母 |
print(string.ascii_letters) |
string.digits/hexdigits/octidgits |
打印所有十進制,十六進制,八進制數 |
print(string.digits) print(string.hexdigits) print(string.octdigits)
輸出
0123456789 0123456789abcdefABCDEF 01234567
|
隨機驗證碼
str_source = string.ascii_letters +string.digits
print("".join(random.sample(str_source,4)))
高級隨機驗證碼
li = []
for i in range(6):
r = random.randrange(0,6)
if r == 3 or r == 2:
tem = random.randrange(0,10)
li.append(str(tem)) #由於在向列表中添加元素時,須要使用字符串類型,所以ASCII中0-10是數字所以須要將其轉爲字符串類型
else:
tem = random.randrange(65,91)
c = chr(tem)
li.append(c)
result = "".join(li) #將生成的列表造成字符串
print(result)
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 |
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 輸出用於分割文件路徑的字符串 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所指向的文件或者目錄的最後修改時間 |
更多猛擊這裏
sys模塊
1 2 3 4 5 6 7 8 |
sys.argv 命令行參數List,第一個元素是程序自己路徑 sys.exit(n) 退出程序,正常退出時exit(0) sys.version 獲取Python解釋程序的版本信息 sys.maxint 最大的Int值 sys.path 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值 sys.platform 返回操做系統 sys.stdout.write('please:') val = sys.stdin.readline()[:-1] |
臺名稱 |
源文檔 <http://www.cnblogs.com/alex3714/articles/5161349.html>
shutil模塊,路徑字符前面 應加r,這樣路徑中出現的\無需被轉譯
shutil.copyfileobj(原文件,目標文件) |
源文件的內容複製到目標文件中,可是須要實現按照須要打開對應的文件 |
with open("123.log","r") as file1,open("456.log","w") as file2: shutil.copyfileobj(f1,f2) |
shutil.copy(src,des) |
將src文件複製到des路徑下,同時拷貝文件和權限
若是des是一個目錄,就會將src文件複製到這個路徑下 若是des是一個文件,則會複製src並將src更名爲des的文件名
注意:路徑前須要加r,r"路徑",複製過去時會連同源文件全部權限一同copy過去
實際上copy方法內部執行了copyfile和copymod兩種方法。copyfile用來複制文件,copymod用來複制權限
|
shutil.copy(r"D:\MyPython\newobject\s14day6\test.py",r"D:\MyPython\newobject\test1.log") # 將test.py複製到test1.log |
shutil.copyfile(src,des) |
shutil.copy方法就是調用的這個方法來複制文件的 |
|
shutil.copymod(src,des) |
shutil.copy方法用來複制用戶權限,此方法僅複製用戶的權限,不復制文件的內容,組和用戶 |
|
shutil.copystat(src,des) |
copy文件的狀態信息,包括修改時間等信息 |
|
shutil.copy2(src,des) |
拷貝文件和狀態信息 |
|
shutil.copytree(src,des) |
拷問目錄,以前的源文件都是一個文件,這個src是一個目錄 |
|
shutil.rmtree(path) |
刪除非空目錄,若是是空目錄能夠用os.removedirs(),方法會逐級刪除路徑上級的空目錄,例如C:/123/234/345,若是345爲空則刪除並檢查234,若是234爲空則刪除並檢查123。 刪除文件:os.remove() |
|
shutil.move(src,des) |
移動文件 |
|
shutil.make_archive(base_name,format,root_dir,owner,group,logger) |
建立壓縮文件 base_name:壓縮包的文件名(文件名會自動放到根目錄下的文件名)或路徑, format:壓縮包格式zip,tar,bztar,gztar, root_dir:被壓縮的文件夾路徑, owner:用戶(默認當前用戶), group:組,默認當前組, loggeer:用於記錄日誌,一般是logging,logger對象 |
shutil.make_archive(r"D:\MyPython\\newobject\\test1","zip",root_dir=r"D:\MyPython\newobject\test") |
zipfile模塊(感受tarfile更好)
import zipfile
# 壓縮
z = zipfile.ZipFile("111.zip","w") # 用w的方式建立一個壓縮文件111.zip,使用ZipFile方法建立壓縮文件,壓縮文件中包含壓縮包的完整目錄結構
z.write("a.log") # 指定想要壓縮的文件
z.write("b.log")
z.write("a.log")
z.close() # 關閉壓縮文件
# 上面的方法就是壓縮文件的方法,能夠指定須要壓縮的文件
# 解壓縮
z = zipfile.ZipFile("111.zip","r") # 用r方式讀取壓縮文件
z.extractall() # 解壓縮所有文件
z.close()
tarfile模塊,打包同時也能夠壓縮的方法。感受比zipfile靈活
import tarfile |
|
||||||||||||||||
tar = tarfile.open(r"d:\your.tar.bz2","w:bz2") |
源文檔 <http://essen.iteye.com/blog/1941489>
|
||||||||||||||||
tar.add(r"D:\MyPython\new object\s13day4",arcname="AAA") |
# 此處若是不指定arcname,則打包後這個文件夾將保留絕對路徑的目錄結構,若是指定了arcname則只有arcname的路徑,例如s13day4裏有一個123.log文件,那麼若是不指定arcname,那麼打包以後的路徑就是[tar_root]\MyPython\new object\s13day4\123.log,若是指定了路徑就是[tar_root]AAA\123.log |
||||||||||||||||
tar.add(r"D:\MyPython\new object\test1.zip",arcname="test.zip") |
|
||||||||||||||||
tar.close() |
|
上面的結果爲:
[tar_root]AAA
[tar_root]test.zip
解包
tar = tarfile.open(r"d:\your.tar","r") |
|
tar.extractall(path=r"D:\MyPython\newobject") |
解包,可設置路徑, |
tar.close() |
|
json模塊和pickle模塊
兩個模塊都提供相同的方法:
json.dump(data,文件名) |
將data轉爲字符串,並寫入文件中 |
json.dumps(data) |
將data轉爲字符串,若是須要寫入文件則 |
json.load(data) |
將一個文件內容轉爲python的數據類型 |
json.loads(data) |
將一個字符串轉爲python的數據類型 |
源文檔 <http://www.cnblogs.com/alex3714/articles/5161349.html>
shelve模塊
是一個簡單的k,v將內存數據經過文件持久化的模塊,能夠支持任何pickle可支持的python數據格式
詳見連接http://www.cnblogs.com/alex3714/articles/5161349.html>
xml模塊
ElementTree 方式建立文檔時,沒法設置縮進
讀取和查詢
python中處理xml語句
例如一個xml
<?xml version="1.0" encoding="utf-8"?> //XML版本信息
<config version="1.0"> //XML的根節點
<Directory>
<DirectoryServerType>UDS</DirectoryServerType>
<ConnectionType>1</ConnectionType>
<PrimaryServerName>142.100.64.11</DirectoryServerName>
<UseWindowsCredentials>0</UseWindowsCredentials>
</Directory>
</config>
import xml.etree.ElementTree as ET |
導入xml模塊 |
tree = ET.parse("test.xml") |
# 打開一個test.xml文件 |
root = tree.getroot() |
# 獲取xml的根節點,此時root的值就是xml裏面的根節點config的內容實際就是整個xml的內容,實際上此時的root是一個迭代器 |
print(root.tag,root.attrib) |
# 打印這個根節點,root.tag就是打印這個根節點的標籤config。.tag是打印標籤的方法 |
for i in root: |
#循環root |
print(i.tag,i.attrib,i.text) |
#遍歷root,tag是標籤,attrib是標籤屬性,text是標籤內容。 <PrimaryServerName>142.100.64.11</DirectoryServerName> tag:PrimaryServerName text:142.100.64.11
<config version="1.0"> tag:config attrib:version="1.0",可是現實時會顯示爲字典格式{'version': '1.0'}
|
若是我須要過濾下面的year標籤,使用iter("year")
<?xml version="1.0"?>
<data>
<year>8888</year>
<country name="china">
<rank updated="yes">2</rank>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
<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>
源文檔 <http://www.cnblogs.com/alex3714/articles/5161349.html>
import xml.etree.ElementTree as ET |
導入xml模塊 |
tree = ET.parse("test.xml") |
# 打開一個test.xml文件 |
root = tree.getroot() |
# 獲取xml的根節點,此時root的值就是xml裏面的根節點config的內容實際就是整個xml的內容,實際上此時的root是一個迭代器 |
for node in root.iter("year"): |
過濾全部標籤爲year的標籤內容,這個遍歷不論層級,只要再當前這個層級一下的標籤爲year就會被遍歷 |
print(node.tag,node.text) |
打印查詢出的標籤的標籤名和內容 |
刪除和修改xml文件
修改
tree = ET.parse("test.xml") |
# 打開一個test.xml文件 |
root = tree.getroot() |
# 獲取xml的根節點,此時root的值就是xml裏面的根節點config的內容實際就是整個xml的內容,實際上此時的root是一個迭代器 |
for node in root.iter("year"): |
|
new_year = int(node.text) + 1 |
#定義一個變量,值爲標籤year的值+1 |
node.text = str(new_year) |
#給year的值賦新值,新值的類型必須是字符串 |
node.set("updated","yes") |
#這句話的意思是出了上面的動做外,我還想要給year增長一個屬性,爲"updated":"yes",這樣year這個標籤就由 <year>XXX</year> 變成
|
tree.write("test.xml",encoding="utf-8") |
最後將更新的XML腳本寫入文件,這個文件能夠是原先的文件也能夠是新文件 |
刪除節點
tree = ET.parse("test.xml") |
# 打開一個test.xml文件 |
root = tree.getroot() |
# 獲取xml的根節點,此時root的值就是xml裏面的根節點config的內容實際就是整個xml的內容,實際上此時的root是一個迭代器 |
for country in root.findall("country"): |
檢索xml文件中,全部country標籤下的內容(findall),由於country下面是標籤,不是內容,因此須要用findall檢索全部的標籤,若是是find("country"),就是檢索下面的內容 |
if int(country.find("rank").text) > 50: |
country.find("rank").text的意思是獲取country標籤下的rank標籤的內容,由於這個內容是字符串,因此須要變爲int類型
|
root.remove(country) |
移除當前這個country的標籤 |
tree.write("test.xml",encoding="utf-8") |
最後將更新的XML腳本寫入文件,這個文件能夠是原先的文件也能夠是新文件 |
建立xml文本
namelist=ET.Element("namelist") |
# 建立一個根標籤namelist |
name=ET.SubElement(namelist,"name",attrib={"test":"yes"}) |
# 建立一個新的標籤,這個標籤是跟標籤namelist下的標籤,標籤名爲name,其屬性是{"test":"yes"}) |
name.text="alex" |
#name標籤的內容爲alex |
age=ET.SubElement(name,"age") |
建立了一個namelist下的標籤名爲age |
age.text="30" |
內容爲30 |
role=ET.SubElement(name,"role") |
|
role.text="teacher" |
|
name=ET.SubElement(namelist,"name",attrib={"test":"yes"}) |
|
name.text="zhangsan" |
|
age=ET.SubElement(name,"age") |
|
age.text="30" |
|
role=ET.SubElement(name,"role") |
|
role.text="ST" |
|
et=ET.ElementTree(namelist) |
文本創建後,生成這個xml語句,由於全部的標籤都是在namelist標籤下,因此直接生成根就能夠 |
et.write("jabber-config3.xml",encoding="utf-8",xml_declaration=True) |
將生成的語句寫入文件xml_declaration=True這句話的意思是生成後的文件裏自動加上版本聲明: <?xmlversion='1.0'encoding='utf-8'?> |
|
|
ET.dump(namelist) |
這個語句是將生成的內容直接在屏幕輸出 |
import xml.dom.minidom as MD
http://www.cnblogs.com/kaituorensheng/p/4493306.html
http://www.oschina.net/question/234345_48732
xml.dom.minidom方法在建立xml文檔時能夠指定縮進,從而造成標準的xml格式
import xml |
導入模塊 |
impl=xml.dom.getDOMImplementation() |
|
namelist=impl.createDocument(None,'namelist',None) |
建立這個文檔namelist |
root=namelist.documentElement |
指定namelist爲根標籤 |
name=namelist.createElement('name') |
在文檔namelist中建立name子標籤 |
name_value=namelist.createTextNode("zhangsan") |
在文檔namelist中間內容name_value |
name.appendChild(name_value) |
將name_value賦值給name |
root.appendChild(name) |
將其加入到根標籤下 |
|
|
age=namelist.createElement('age') |
在文檔namelist中建立子標籤age |
age.setAttribute("attr","30") |
設置age標籤的屬性爲attr = 30 |
age_value=namelist.createTextNode("222") |
在文檔namelist中建立一個文本節點age_value |
age.appendChild(age_value) |
將age_value賦值給age |
name.appendChild(age) |
將age標籤追加到name下 |
file=open('1.xml','w',encoding='utf-8') |
打開文檔 |
namelist.writexml(file,addindent=" '',newl="\n",encoding='utf-8') |
將namelist文檔寫入,addindent設置每級標籤的縮進,newl設置了xml中每一行的換行方式 |
file.close() |
關閉文檔 |
下面的例子是經過循環的方式建立xml文件
import xml
from xml.dom import minidom
list = [("zhangsan","30"),("lisi","40"),("wangwu","50")]
impl=xml.dom.getDOMImplementation()
namelist=impl.createDocument(None,'namelist',None)
root=namelist.documentElement
for i in list:
name=namelist.createElement('name')
name_value=namelist.createTextNode(i[0])
name.appendChild(name_value)
root.appendChild(name)
age=namelist.createElement('age')
age.setAttribute("attr",i[1])
age_value=namelist.createTextNode(i[1])
age.appendChild(age_value)
name.appendChild(age)
f=open('1.xml','w',encoding='utf-8')
namelist.writexml(f,addindent=" ",newl="\n",encoding='utf-8')
f.close()
輸出結果爲
<?xml version="1.0" encoding="utf-8"?>
<namelist>
<name>
zhangsan
<age attr="30">30</age>
</name>
<name>
lisi
<age attr="40">40</age>
</name>
<name>
wangwu
<age attr="50">50</age>
</name>
</namelist>
ConfigParser模塊
用於生成和修改常見配置文檔,當前模塊在python3.x版本改名爲configparser
配置文件
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no
源文檔 <http://www.cnblogs.com/alex3714/articles/5161349.html>
要建立上面的文件 按以下寫法
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'] # 第三種,將key做爲變量直接追加,總之都 topsecret['Host Port'] = '50022' # mutates the parser # 是按字典的方式寫,將標籤看作key裏面的 topsecret['ForwardX11'] = 'no' # same here # 內容做爲value config['DEFAULT']['ForwardX11'] = 'yes' # 看好標籤,追加到哪裏了?
with open('example.ini', 'w') as configfile: config.write(configfile) # 此處寫入文檔時的方法和open不同 注意! |
源文檔 <http://www.cnblogs.com/alex3714/articles/5161349.html>
讀取配置文件
import configparser |
|
config = configparser.ConfigParser() |
|
print(config.sections()) |
此時sections裏什麼都沒有由於沒有讀任何內容,輸出: |
config.read('example.ini') |
讀取一個配置文件 |
print(config.sections()) |
此時sections裏會顯示出了DEFAULT標籤外的其餘標籤 |
print('bitbucket.org' in config) |
檢查標籤是否存在在配置文件內 |
print('bytebong.com' in config) |
False |
print(config['bitbucket.org']['User']) |
獲取特定標籤的值,若是沒有回報錯 |
print(config['bitbucket.org'].get('User1')) |
使用這種方法,若是沒有會返回 |
topsecret = config['topsecret.server.com'] print(topsecret['ForwardX11']) |
同理 能夠賦值一個key獲取 |
for key in config['bitbucket.org']: print(key) |
循環的方式獲取key,出了當前的key還有DEFAULT的 |
for key,v in config['bitbucket.org'].items():print(key,v) |
連值一塊兒取 |
print(config.options('bitbucket.org')) |
options方法,是能夠以列表的形式輸出出當前的標籤裏的key和DEFAULT裏的key 配置文件中內容解釋 section:就是[DEFAULT]這樣的標籤 option:是標籤內的內容ServerAliveInterval = 45 所以 config.options('bitbucket.org')的意思就是打印配置文件中bitbucket.org標籤下的內容 |
print(config.items('bitbucket.org')) |
items方法,以元祖形式輸出當前標籤和DEFAULT裏的key和值 |
源文檔 <http://www.cnblogs.com/alex3714/articles/5161349.html>
刪除內容
config.remove_option("DEFAULT","compression") |
刪除特定section中的特定的option |
with open('example1.ini', 'w') as configfile: config.write(configfile) |
將刪除後的配置文件保存 |
config.remove_section("bitbucket.org") |
刪除特定的section |
with open('example1.ini', 'w') as configfile: config.write(configfile) |
|
更改內容
config.set("DEFAULT","compressionlevel","8888") |
變動option的值,括號內的內容一次爲section,option,value |
增長內容
config.add_section("zhangsan") |
增長一個section |
config["liubo"]["age"] = "30" |
給這個section增長一個option並賦值 |
config.write(open("example4.ini","w")) |
寫入文件 |
判斷是否存在
print(config.has_section("lisi")) |
判斷是否存在特定的section |
print(config.has_option("lisi","age")) |
判斷在特定的section中是否存在option,括號內的順序爲section,option |
hashlib散列
md5等方法沒法反解,但可能被暴力破解(即攻擊者窮舉法md5每一個密碼,將結果與md5值對比來破解)
散列將任意長度的字符串轉成特定長度的字符串,hash的特色爲輸入固定則輸出必定固定,輸入變化輸出必定變化。進行文件一致性驗證
散列的方式能夠有md5,sha1,sha256,sha384,sha512,一般使用sha256,下例採用md5方式,其餘方法值須要變動散列方式便可(m = hashlib.sha256())
import hashlib |
導入hashlib模塊 |
m = hashlib.md5() |
|
m.update(b"alex") |
對alex這個字符串進行md5操做,字符串必須是字節形式(b)才能md5 |
print(m.hexdigest()) |
以十六進制形式輸出 |
對於hashlib.md5來講,
m.update(b"alex")
print(m.hexdigest())
m.update(b"liubo")
print(m.hexdigest())
最終輸入的m.hexdigest和
m.update(b"alexliubo")
print(m.hexdigest())
輸出的值是同樣的,
其意義在於,當咱們對文件進行散列時,徹底能夠用for循環逐行update,最終的結果和直接將文件所有加載再散列是同樣的。當文件很是龐大時咱們不須要一次性加載再總體散列。使用for循環的方式確定會比整個文件散列要慢,可是這樣作能夠節約內存空間。
hmac模塊
hmac對建立的kye和內容進行處理後再加密,安全性比hash高
通常用於網絡消息加密傳輸,其加密性能比hash256要好
import hmac |
|
h_obj = hmac.new(b"key",b"cisco,123") |
第一個參數爲key就是hmac在處理時加入在正式內容中的key,key能夠爲任何字符串,第二個參數是要加密的字符串 |
print(h_obj.exdigest()) |
打印結果 |
Subprocess模塊
此模塊會替換os.system()和os.spawn方法。
logging模塊
日誌處理模塊
logging模塊
import logging
logging.warning("")
logging.critical("")
logging日誌級別(從上向下級別愈來愈高,debug最低)
DEBUG |
最詳細的日誌級別,用於故障排查 |
INFO |
一些通用時間 |
WARNING |
一些非預期的時間發生,代表出現了一些問題,可是軟件仍然工做 |
ERROR |
一些使軟件的功能沒法正常工做的錯誤 |
CRITICAL |
一系列的ERROR,軟件已經沒法繼續運行 |
將文件記錄進文件的方法
logging.basicConfig(filename="文件名",level=logging.INFO) # 只有日誌級別不低於INFO的日誌纔會被記錄到文件中
logging.debug("")
logging.info("")
logging.warning("")
將時間記錄今日誌
logging.basicConfig(filename="文件名",level=logging.INFO,format="%(asctime)s %(message)s",datefmt="%m%d%Y %I:%M:%S %p")
在上面的例子中,asctime和message都是佔位符,表明未來額日誌先顯示時間,後顯示消息。datefmt則是時間的格式
同時將日誌打印到屏幕和日誌文件中
logging模塊有4個部分:
logger |
是一個接口,用來產生日誌條目 |
handlers |
發送日誌條目到指定的目的地(日誌條目由logger產生) |
filters |
提供一種日誌過濾的方法(關鍵字等) |
formatters |
將日誌格式化輸出 |
import logging
# create logger
logger = logging.getLogger("TEST-LOG") # 首先獲取logger這個對象
logger.setLevel(logging.DEBUG) # 設定一個全局的日誌級別
# create console handler and set level to debug
ch = logging.StreamHandler() # 在屏幕上打印日誌條目
ch.setLevel(looging.DEBUG) # 指定在屏幕上打印debug以上級別的信息
# create file handler and set level to waring
fh = logging.FileHandler("access.log") # 在文件上打印日誌條目
fh.setLevel(logging.WARNING) # 指定打印warning以上級別的信息到文件中
# create formatter
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s" # %(name)s 這個變量指代的就是getLogger中的文本"TEST-LOG"
formatter_file = logging.Formatter("%(asctime)s - %(name)s - %(evelname)s - %(message)s")
# add formatter to ch and fh
ch.setFormatter(formatter) # 傳遞給屏幕上的日誌條目應該按照formatter的格式輸出
fh.setFormatter(formatter_file) # 傳遞給文件的日誌條目應該按照formatter_file的格式輸出
# add ch and fh to logger
logger.addHandler(ch) # 告訴logger將日誌按照ch的設置輸出到屏幕上
logger.addHandler(fh) # 告訴logger將日誌按照fh的設置輸出到文件中
logger.debug("") # 調用建立的logger來記錄數據
logger.info("")
logger.warning("")
logger.error("")
logger.critical("")
在上面的例子中 logger和handle都定義了level,在這裏 logger是全局的日誌級別,他定義了最低能顯示的級別,handler的級別只能等於或高於logger的級別
在同一個logger中被多個同類handler調用,就會生成多條相同的記錄(好比我想要同一個logger,分別向2個文件輸出,那麼每一個文件中都會獲得2條同樣的數據)。所以若是我須要同時向多個文件輸出日誌,就須要建立多個logger handler來分開記錄。
filename:用指定的文件名建立FiledHandler(後邊會具體講解handler的概念),這樣日誌會被存儲在指定的文件中。
filemode:文件打開方式,在指定了filename時使用這個參數,默認值爲「a」還可指定爲「w」。
format:指定handler使用的日誌顯示格式。
datefmt:指定日期時間格式。
level:設置rootlogger(後邊會講解具體概念)的日誌級別
stream:用指定的stream建立StreamHandler。能夠指定輸出到sys.stderr,sys.stdout或者文件,默認爲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 |
用戶輸出的消息 |
源文檔 <http://blog.csdn.net/zyz511919766/article/details/25136485/>
logging.handlers.RotatingFileHandler() |
此方法用於管理日誌文件大小,當文件達到必定大小以後,它會自動將當前 日誌文件更名,而後建立一個新的同名文件繼續輸入 |
日誌分割(按大小分割)
import logging |
引入模塊 |
logger = logging.getLogger("log") |
定義一個名爲log的logger |
log_file = "time.log" |
|
logger.setLevel(logging.DEBUG) |
|
# fh = logging.FileHandler(log_file,encoding="utf-8") |
這是原來定義的沒有分割的方法,只是定義日誌的文件名 |
fh = handlers.RotatingFileHandler(filename = log_file,maxBytes = 10,backupCount = 3,encoding="utf-8") |
如今使用新的方法,這個方法出了定義了文件位置,還定義了一個文件最大的大小爲10字節,而且只保留3個(即當出現第四個日誌文件時,第一個會被刪除,滾動輸出),utf-8編碼保證了輸出中文時不亂碼,若是maxBytes爲0則不分割 |
fh.setLevel(logging.WARNING) |
|
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s" # %(name)s) |
|
fh.setFormatter(formatter) |
|
logger.addHandler(fh) |
|
日誌分割(按時間)
fh = handlers.TimeRotatingFileHandler(filename=log_file,when="S",interval=5,backupCount=3)i |
when指定了時間的單位: M 分 H 小時 D 天(以當前生效時間開始計時) W 每星期(interval = 0則爲星期一) midnight 天天凌晨
|
正則表達式模塊 re模塊
import re |
引入正則模塊 |
a = re.match("規則","str") |
match根據定義的規則,從字符串的開頭開始匹配 |
print(a.group()) |
輸出結果 |
re.match(規則,字符串) |
從頭開始匹配 |
|
re.search(規則,字符串) |
匹配包含,可是隻返回第一次匹配的結果 |
這是經常使用方法 |
re.findall(規則,字符串) |
把全部匹配到的字符放到以列表中的元素返回 |
|
re.split(規則,字符串) |
以匹配到的字符當作列表分隔符,不管如何匹配以及匹配了多長的字符,只要匹配了 他就是分隔符,輸出的是被分割的結果 |
|
re.sub(規則,替換字符串,原字符串) |
匹配字符並替換 |
|
源文檔 <http://www.cnblogs.com/alex3714/articles/5161349.html>
正則表達式符號
'.' |
默認匹配除\n以外的任意一個字符,若指定flag DOTALL,則匹配任意字符,包括換行 |
'^' |
匹配字符開頭,若指定flags MULTILINE,這種也能夠匹配上(r"^a","\nabc\neee",flags=re.M) |
'$' |
匹配字符結尾,或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("(\w{2})a(123|456)c", "abcabca456c").group() 結果 bca456c 當使用groups()時則顯示('bc', '456'),小括號表明將查詢規則分組,group沒有特別的就顯示了匹配的結果,而goups則按照分組顯示匹配到的內容,顯示結果爲元組 |
'\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'},這種方法能夠將以前()的分組顯示爲字典並加入key |
源文檔 <http://www.cnblogs.com/alex3714/articles/5161349.html>
a.group() |
顯示匹配的完整字符串 |
a.groups() |
根據分組顯示匹配的分組字符串 |
re.search和re.findall
import re
str1 ="""
以太網適配器 VMware Network Adapter VMnet8:
鏈接特定的 DNS 後綴 . . . . . . . :
本地連接 IPv6 地址. . . . . . . . : fe80::78c3:7b4c:577d:3c05%19
IPv4 地址 . . . . . . . . . . . . : 192.168.44.1
子網掩碼 . . . . . . . . . . . . : 255.255.255.0
默認網關. . . . . . . . . . . . . :
"""
print(re.search("(\d{1,3}\.){3}(\d{1,3})",str1).group())
匹配IP地址的規則,在這裏由於"."在正則表達式中表明任意一位字符,所以此處必須轉譯"\."
若是我想取出 IP 和掩碼,就須要用re.findall,並且規則也要變化,並且由於findall是以列表輸出,所以不能使用group
print(re.findall("(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})",str1))
re.sub
print(re.sub("(\d{1,3}\.){3}(\d{1,3})","333.333.33.3",str1))
輸出
以太網適配器 VMware Network Adapter VMnet8:
鏈接特定的 DNS 後綴 . . . . . . . :
本地連接 IPv6 地址. . . . . . . . : fe80::78c3:7b4c:577d:3c05%19
IPv4 地址 . . . . . . . . . . . . : 333.333.33.3
子網掩碼 . . . . . . . . . . . . : 333.333.33.3
默認網關. . . . . . . . . . . . . :
========================================================================================
若是指定count,則只替換count次
print(re.sub("(\d{1,3}\.){3}(\d{1,3})","333.333.33.3",str1,count=1))
以太網適配器 VMware Network Adapter VMnet8:
鏈接特定的 DNS 後綴 . . . . . . . :
本地連接 IPv6 地址. . . . . . . . : fe80::78c3:7b4c:577d:3c05%19
IPv4 地址 . . . . . . . . . . . . : 333.333.33.3
子網掩碼 . . . . . . . . . . . . : 255.255.255.0
默認網關. . . . . . . . . . . . . :
r"字符串"
r"字符串"表明字符串中的內容不管有何意義都不作處理當作純文本內容,例如一個路徑,由於其分割爲\:D:\MyPython\new object\s14day6\time.log.1
這是若是直接"D:\MyPython\new object\s14day6\time.log.1",那麼裏面的\會被認爲爲轉移符,那麼當咱們制定爲r"D:\MyPython\new object\s14day6\time.log.1"時,則裏面的\或者裏面有任何可能被認爲是有其餘用法的符號都會被當作字符串的一部分沒有特殊意義。
反斜槓的困擾
與大多數編程語言相同,正則表達式裏使用"\"做爲轉義字符,這就可能形成反斜槓困擾。假如你須要匹配文本中的字符"\",那麼使用編程語言表示的正則表達式裏將須要4個反斜槓"\\\\":前兩個和後兩個分別用於在編程語言裏轉義成反斜槓,轉換成兩個反斜槓後再在正則表達式裏轉義成一個反斜槓。Python裏的原生字符串很好地解決了這個問題,這個例子中的正則表達式可使用r"\\"表示。一樣,匹配一個數字的"\\d"能夠寫成r"\d"。有了原生字符串,你不再用擔憂是否是漏寫了反斜槓,寫出來的表達式也更直觀。
源文檔 <http://www.cnblogs.com/alex3714/articles/5161349.html>
原本在寫正則表達式時,匹配\時應該寫成\\,可是當使用python寫的時候,正則中的2個\ 又必需要被轉譯 所以\\\\才能匹配正則表達式中的\\ 實際匹配一個\。而用r"\\"則能夠省略4個\\\\
所以當我須要替換\:
print(re.sub(r"\\","%",r"D:\MyPython\newobject\s14day6\time.log.1"))
輸出
D:%MyPython%new object%s14day6%time.log.1
僅需輕輕知道的幾個匹配模式
在re的全部模塊參數中,都存在一個flag參數,其值能夠設置一些匹配的功能
re.I(re.IGNORECASE): 忽略大小寫(括號內是完整寫法,下同) |
print(re.search("^a.*","ABC")),這樣由於a是小寫,沒法匹配A |
re.M(MULTILINE): 多行模式,改變'^'和'$'的行爲(參見上圖) |
print(re.search(r"^a","\nabc\neee",flags=re.M)),這裏字符串 以\n開頭,表明第一行爲空a是第二行開頭,那麼若是不加re.M則匹配不上,加了之後就變爲多行模式a爲第二行的開始,就能夠匹配上 |
re.S(DOTALL): 點任意匹配模式,改變'.'的行爲 |
.這個符號在正則中表明任意字符,可是除了\n,這樣也就是說他能夠匹配一行中的任意字符,可是若是字符串時多行的,由於.沒法表明換行符,他仍然只能匹配一行的字符,沒法返回多行,那麼這就須要flags=re.S,這樣.就能夠指代換行符,在多行的字符串中一個.+,就能夠匹配所有多行的字符串 |
當咱們要將某些字符加入特定的前綴時,須要re.sub結合lambda函數使用
re.sub("\d{1,4}",lambdamatch:"AA"+match.group(),line) |
替換部分的函數時這樣的,其默認會將match部分的內容做爲參數傳入函數中,此時咱們能夠經過match.group()來取得匹配的內容 |
下面是上面例句的完整例子:
需求,在配置網關時,咱們但願將網關的dial-peer編號加上特定的前綴
配置文件:
dial.log
dial-peer voice 102 pots
translation-profile incoming E1-incoming
port 0/1/0:15
!
dial-peer voice 1023 pots
translation-profile incoming E1-incoming
port 0/1/1:15
!
dial-peer voice 1 pots
translation-profile incoming E1-incoming
port 0/0/0:15
!
dial-peer voice 10 pots
translation-profile incoming E1-incoming
port 0/0/1:15
with open("dial.log","r",encoding="utf-8") as file1,open("dial1.log","w",encoding="utf-8") as file2:
for line in file1:
if re.search("^dial",line.strip()):
file2.write(re.sub("\d{1,4}",lambda match:"AA" + match.group(),line).strip() + "\n")
else:
file2.write(line.strip() + "\n")
新配置文件:
dial1.log
dial-peer voice AA102 pots
translation-profile incoming E1-incoming
port 0/1/0:15
!
dial-peer voice AA1023 pots
translation-profile incoming E1-incoming
port 0/1/1:15
!
dial-peer voice AA1 pots
translation-profile incoming E1-incoming
port 0/0/0:15
!
dial-peer voice AA10 pots
translation-profile incoming E1-incoming
port 0/0/1:15
本節做業
一、實現加減乘除及括號優先級的解析
二、用戶輸入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等相似公式後,必須本身解析裏面的(),+,-,*,/符號和公式(不能調用eval等相似功能偷懶實現),運算後得出結果,結果必須與真實的計算器所得出的結果一致
[^()]+