一 time & datetimehtml
在Python中,一般有以下幾種方式來表示時間:node
>>> import time #-------------------------如下分別是三種形式的時間-----------------------# >>> print(time.time()) #時間戳 1509802396.6130548 >>> print(time.strftime('%Y-%m-%d %X')) #格式化的時間字符串,默認按當前時間(time.localtime())進行格式化 2017-11-04 21:34:03 >>> print (time.strftime('%a %b %d %H:%M:%S %Y')) #格式化的時間字符串,同上一個 Sat Nov 04 21:35:40 2017 >>> print(time.localtime()) #本地時區的struct_time time.struct_time(tm_year=2017, tm_mon=11, tm_mday=4, tm_hour=21, tm_min=34, tm_sec=40, tm_wday=5, tm_yday=308, tm_isdst=0) >>> print(time.gmtime()) #UTC時區的struct_time time.struct_time(tm_year=2017, tm_mon=11, tm_mday=4, tm_hour=13, tm_min=34, tm_sec=57, tm_wday=5, tm_yday=308, tm_isdst=0)
%y 去掉世紀的年份表示(00 - 99) %Y 完整的年份表示(0000 - 9999) %m 月份(01 - 12) %d 一個月中的第幾天(01 - 31) %H 24小時制小時數(00 - 23) %I 12小時制小時數(01 - 12) %M 分鐘數(00 - 59) %S 秒(00 - 59) %a 本地(locale)簡化星期名稱 %A 本地完整星期名稱 %b 本地簡化的月份名稱 %B 本地完整的月份名稱 %c 本地相應的日期表示和時間表示 %j 一年中的第幾天(001 - 366) %p 本地A.M.或P.M.的等價符 %U 一年中的星期數(00 - 53)星期天爲星期的開始 %w 一個星期中的第幾天(0 - 6),星期天爲星期的開始 %W 和%U基本相同,不一樣的是%W是以星期一爲一個星期的開始 %x 本地相應的日期表示 %X 本地相應的時間表示 %Z 當前時區的名稱(若是不存在爲空字符) %% %號自己
其中計算機認識的時間只能是'時間戳'格式,而程序員可處理的或者說人類能看懂的時間有: '格式化的時間字符串','結構化的時間' ,因而有了下圖的轉換關係python
>>> import time #-------------------------------------按圖1轉換時間------------------------------------------# # localtime([secs]):將一個時間戳轉換爲當前時區(UTC+8)的struct_time。secs參數未提供,則以當前時間爲準。 >>> time.localtime() time.struct_time(tm_year=2017, tm_mon=11, tm_mday=4, tm_hour=21, tm_min=57, tm_sec=41, tm_wday=5, tm_yday=308, tm_isdst=0) >>> x = time.localtime(1509802396.6130548) >>> print(x) time.struct_time(tm_year=2017, tm_mon=11, tm_mday=4, tm_hour=21, tm_min=33, tm_sec=16, tm_wday=5, tm_yday=308, tm_isdst=0) >>> print(x.tm_year) 2017 >>> print(x.tm_yday) 308 # gmtime([secs]) 和localtime()方法相似,gmtime()方法是將一個時間戳轉換爲UTC時區(0時區)的struct_time。 # mktime(t) : 將一個struct_time轉化爲時間戳。 >>> print(time.mktime(time.localtime())) 1509803970.0 # strftime(format[, t]) : 把一個表明時間的元組或者struct_time(如由time.localtime()和time.gmtime()返回)轉化爲格式化的時間字符串。 若是t未指定,將傳入time.localtime()。若是元組中任何一個元素越界,ValueError的錯誤將會被拋出。 >>> print(time.strftime("%Y-%m-%d %X", time.localtime())) 2017-11-04 22:00:32 >>> print(time.strftime("%X %Y-%m-%d", time.localtime())) 22:00:32 2017-11-04 # time.strptime(string[, format]):把一個格式化時間字符串轉化爲struct_time。實際上它和strftime()是逆操做。 >>> print(time.strptime('2017-11-04 22:00:32', '%Y-%m-%d %X')) time.struct_time(tm_year=2017, tm_mon=11, tm_mday=4, tm_hour=22, tm_min=0, tm_sec=32, tm_wday=5, tm_yday=308, tm_isdst=-1) #在這個函數中,format默認爲:"%a %b %d %H:%M:%S %Y"。
>>> import time #將格式字符串轉換爲時間戳 >>> string_to_struct = time.strptime("2017-10-30 14:48:44","%Y-%m-%d %H:%M:%S") #將 日期字符串 轉成 struct時間對象格式 >>> print(string_to_struct) time.struct_time(tm_year=2017, tm_mon=10, tm_mday=30, tm_hour=14, tm_min=48, tm_sec=44, tm_wday=0, tm_yday=303, tm_isdst=-1) >>> struct_to_stamp = time.mktime(string_to_struct) #將struct時間對象格式轉成時間戳 >>> print(struct_to_stamp) 1509346124.0 或者一步到位 >>> print(time.mktime(time.strptime("2017-10-30 14:48:44","%Y-%m-%d %H:%M:%S")) ) 1509346124.0 #將時間戳轉換爲格式字符串 >>> print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(1509346124.0)) ) 2017-10-30 14:48:44
>>> import time #-----------------------------------------按圖2轉換時間-------------------------------------------# # asctime([t]) : 把一個表示時間的元組或者struct_time表示爲這種形式:'Sun Jun 20 23:21:05 1993'。若是沒有參數,將會將time.localtime()做爲參數傳入。 >>> print(time.asctime()) Sat Nov 4 22:19:37 2017 # ctime([secs]) : 把一個時間戳(按秒計算的浮點數)轉化爲time.asctime()的形式。若是參數未給或者爲None的時候,將會默認time.time()爲參數。
它的做用至關於time.asctime(time.localtime(secs))。 >>> print(time.ctime()) Sat Nov 4 22:19:56 2017 >>> print(time.ctime(time.time())) Sat Nov 4 22:20:35 2017 #---------------------------------------其它用法---------------------------# # sleep(secs):線程推遲指定的時間運行,單位爲秒。
#時間加減 >>> import datetime >>> print(datetime.datetime.now()) #返回當前時間 2017-11-04 22:28:16.976757 >>> print(datetime.date.fromtimestamp(time.time()) ) # 時間戳直接轉成日期格式 2017-11-04 >>> print(datetime.datetime.now() ) 2017-11-04 22:29:12.067908 >>> print(datetime.datetime.now() + datetime.timedelta(3)) #當前時間+3天 2017-11-07 22:29:24.544621 >>> print(datetime.datetime.now() + datetime.timedelta(-3)) #當前時間-3天 2017-11-01 22:29:38.412414 >>> print(datetime.datetime.now() + datetime.timedelta(hours=3)) #當前時間+3小時 2017-11-05 01:29:50.667115 >>> print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #當前時間+30分 2017-11-04 23:00:03.260836 >>> c_time = datetime.datetime.now() >>> print(c_time.replace(minute=3,hour=2)) #時間替換 2017-11-04 02:03:37.749808
二 randommysql
隨機數程序員
>>> import random >>> print(random.random()) #(0,1)----float 大於0且小於1之間的小數。也能夠指定區間,看下一個 0.4389206383156363 >>> print(random.uniform(1,3)) #大於1小於3的小數 1.8623602068930234 >>> print(random.randint(1,3)) #[1,3] 大於等於1且小於等於3之間的整數 1 >>> print(random.randrange(1,3)) #[1,3) 大於等於1且小於3之間的整數 2 >>> print(random.choice([1,'23',[4,5]])) #1或者23或者[4,5] 23 >>> print(random.sample([1,'23',[4,5]],2)) #列表元素任意2個組合 ['23', 1] >>> item=[1,3,5,7,9] >>> random.shuffle(item) #打亂item的順序,至關於"洗牌" >>> print(item) [7, 3, 1, 5, 9]
>>> import random >>> def make_code(n): res = '' for i in range(n): s1 = chr(random.randint(65,90)) s2 = str(random.randint(0,9)) res += random.choice([s1,s2]) return res >>> print(make_code(9)) 5Z126T88M
三 OS模塊正則表達式
OS模塊是於操做系統交互的一個接口算法
import 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下爲"\r\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的大小
更多猛擊這裏sql
>>> import os # 在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,sys >>> possible_topdir = os.path.normpath(os.path.join( os.path.abspath(os.__file__), os.pardir, os.pardir, os.pardir )) >>> sys.path.insert(0,possible_topdir) #方式二:不推薦使用 import os >>> os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(os.__file__)))) 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python'
四 sys模塊shell
1 sys.argv # 命令行參數List,第一個元素是程序自己路徑 2 sys.exit(n) # 退出程序,正常退出時exit(0) 3 sys.version # 獲取Python解釋程序的版本信息 4 sys.maxint # 最大的Int值 5 sys.path # 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值 6 sys.platform # 返回操做系統平臺名稱 7 sys.stdout.write('please:') 8 val = sys.stdin.readline()[:-1]
#=========知識儲備========== #進度條的效果 [# ] [## ] [### ] [#### ] #指定寬度 print('[%-15s]' %'#') print('[%-15s]' %'##') print('[%-15s]' %'###') print('[%-15s]' %'####') #打印% print('%s%%' %(100)) #第二個%號表明取消第一個%的特殊意義 #可傳參來控制寬度 print('[%%-%ds]' %50) #[%-50s] print(('[%%-%ds]' %50) %'#') print(('[%%-%ds]' %50) %'##') print(('[%%-%ds]' %50) %'###') #=========實現打印進度條函數========== import sys import time def progress(percent,width=50): if percent >= 1: percent=1 show_str=('[%%-%ds]' %width) %(int(width*percent)*'#') print('\r%s %d%%' %(show_str,int(100*percent)),file=sys.stdout,flush=True,end='') #=========應用========== data_size=1025 recv_size=0 while recv_size < data_size: time.sleep(0.1) #模擬數據的傳輸延遲 recv_size+=1024 #每次收1024 percent=recv_size/data_size #接收的比例 progress(percent,width=70) #進度條的寬度70
五 shutil模塊json
高級的文件、文件夾、壓縮包處理模塊。包括複製、移動、重命名、刪除等等。
shutil.copyfileobj(fsrc, fdst[, length])
將文件內容拷貝到另外一個文件中
>>> import shutil >>> shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
shutil.copyfile(src, dst)
拷貝文件
>>> shutil.copyfile('f1.log', 'f2.log') #目標文件無需存在,通常不用
shutil.copymode(src, dst)
僅拷貝權限。內容、組、用戶均不變。
>>> shutil.copymode('f1.log', 'f2.log') #目標文件必須存在,通常不用
shutil.copystat(src, dst)
僅拷貝狀態的信息,包括:mode bits, atime, mtime, flags
>>> shutil.copystat('f1.log', 'f2.log') #目標文件必須存在,通常不用
shutil.copy(src, dst)
拷貝文件和權限
>>> import shutil >>> shutil.copy('f1.log', 'f2.log')
shutil.copy2(src, dst)
拷貝文件和狀態信息
>>> import shutil >>> shutil.copy2('f1.log', 'f2.log')
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
遞歸的去拷貝文件夾
>>> import shutil >>> shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目標目錄不能存在,
注意對folder2目錄父級目錄要有可寫權限,ignore的意思是排除
>>> import shutil >>> shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) ''' 一般的拷貝都把軟鏈接拷貝成硬連接,即對待軟鏈接來講,建立新的文件 '''
shutil.rmtree(path[, ignore_errors[, onerror]])
遞歸的去刪除文件
>>> import shutil >>> shutil.rmtree('folder1')
shutil.move(src, dst)
遞歸的去移動文件,它相似mv命令,其實就是重命名。
>>> import shutil >>> shutil.move('folder1', 'folder3')
shutil.make_archive(base_name,format,...)
建立壓縮包並返回文件路徑,例如:zip、tar
如:data_bak =>保存至當前路徑
如:/tmp/data_bak =>保存至/tmp/test/
#將 /data 下的文件打包放置當前程序目錄 >>> import shutil >>> shutil.make_archive('data_bak','tar',root_dir='/data') '/root/data_bak.tar' #將 /data下的文件打包放置 /tmp/ 目錄 >>> shutil.make_archive('/tmp/data_bak','tar',root_dir='/data') '/tmp/data_bak.tar'
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()
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()
六 json & pickle模塊
用於序列化的兩個模塊
json模塊提供了四個功能:dumps、dump、loads、load
pickle模塊提供了四個功能:dumps、dump、loads、load
>>> import pickle >>> data = {'k1':123,'k2':'Hello'} # pickle.dumps 將數據經過特殊的形式裝換爲只有python語言認識的字符串 >>> p_str = pickle.dumps(data) >>> print(p_str) b'\x80\x03}q\x00(X\x02\x00\x00\x00k1q\x01K{X\x02\x00\x00\x00k2q\x02X\x05\x00\x00\x00Helloq\x03u.' # pickle.dump 將數據經過特殊的形式裝換爲只有python語言認識的字符串,並寫入文件 >>> with open(r'D:\result.pk','wb') as fp: pickle.dump(data,fp) #讀取pickle文件 >>> with open(r'D:\result.pk','rb') as fp: pickle.load(fp) {'k2': 'Hello', 'k1': 123} >>> import json # json.dumps 將數據經過特殊的形式轉換爲全部程序語言都認識的字符串 >>> j_str = json.dumps(data) >>> print(j_str) {"k2": "Hello", "k1": 123} # json.dumps 將數據經過特殊的形式轉換爲全部程序語言都認識的字符串,並寫入文件 >>> with open(r'D:\result.json','w') as fp: json.dump(data,fp) #讀取json文件 >>> with open(r'D:\result.json','r') as fp: json.load(fp) {'k2': 'Hello', 'k1': 123}
七 shelve模塊
shelve模塊是一個簡單的k,v將內存數據經過文件持久化的模塊,能夠持久化任何pickle可支持的python數據格式,而且能夠屢次 dump 和 load
>>> import shelve >>> import datetime #持久化數據 >>> info = {'name': 'bigberg', 'age': 22} >>> name = ['Apoll', 'Zous', 'Luna'] >>> t = datetime.datetime.now() >>> with shelve.open('/tmp/shelve.txt') as f: #執行代碼後會生成3個文件:shelve.txt.bak、shelve.txt.dat、shelve.txt.dir。 ... f['name'] = name #持久化列表 ... f['info'] = info #持久化字典 ... f['time'] = t #持久化時間類型 ... #讀取數據 >>> with shelve.open('shelve.txt') as f: #打開文件 ... print(f.get('name')) #使用get獲取數據 ... print(f.get('info')) ... print(f.get('time')) ... ['Apoll', 'Zous', 'Luna'] {'name': 'bigberg', 'age': 22} 2017-11-01 16:07:29.261414
八 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協議在各個語言裏的都 是支持的,在python中能夠用如下模塊操做xml:
print(root.iter('year')) #全文搜索 print(root.find('country')) #在root的子節點找,只找一個 print(root.findall('country')) #在root的子節點找,找全部
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,child.attrib['name']) for i in child: print(i.tag,i.attrib,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') node.set('version','1.0') tree.write('test.xml') #刪除node for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('output.xml')
#在country內添加(append)節點year2 import xml.etree.ElementTree as ET tree = ET.parse("a.xml") root=tree.getroot() for country in root.findall('country'): for year in country.findall('year'): if int(year.text) > 2000: year2=ET.Element('year2') year2.text='新年' year2.attrib={'update':'yes'} country.append(year2) #往country節點下添加子節點 tree.write('a.xml.swap')
本身建立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) #打印生成的格式
九 configparser模塊
用於生成和修改常見配置文檔。
一個典型的Mysql配置文件以下:
[mysqld] port = 3306 socket = /var/lib/mysql/mysql.sock key_buffer = 384M myisam_sort_buffer_size = 64M thread_cache_size = 8 query_cache_size = 32M max_connections=500 thread_concurrency = 8 [client] user = root password = 123456 port = 3306 socket = /var/lib/mysql/mysql.sock
讀取
>>> import configparser >>> config=configparser.ConfigParser() >>> config.read('my.cnf') ['my.cnf'] #查看全部的標題 >>> res=config.sections() >>> print(res) ['mysqld', 'client'] #判斷是否存在某個標題 >>> 'mysqld' in config True >>> print(config.has_section('mysqld')) #同上一個 True #判斷標題mysqld下是否有user >>> print(config.has_option('mysqld','user')) False #查看標題client下全部key=value的key >>> options=config.options('client') >>> print(options) ['user', 'password', 'port', 'socket'] >>> for key in config['client']:print(key) #同上一個 ... user password port socket #查看標題client下全部key=value的(key,value)格式 >>> item_list=config.items('client') >>> print(item_list) [('user', 'root'), ('password', '123456'), ('port', '3306'), ('socket', '/var/lib/mysql/mysql.sock')] #查看標題client下user的值=>字符串格式 >>> val=config.get('client','user') >>> print(val) root >>> config['client']['user'] #同上一個 'root' #查看標題client下port的值=>整數格式 >>> val1=config.getint('client','port') >>> print(val1) 3306 #查看標題mysqld下mysql_update的值=>布爾值格式 val2=config.getboolean('mysqld','mysql_update') print(val2) #查看標題mysqld下max_connections的值=>浮點型格式 val3=config.getfloat('mysqld','max_connections') print(val3)
改寫
>>> import configparser >>> config=configparser.ConfigParser() >>> config.read('my.cnf',encoding='utf-8') ['my.cnf'] #刪除整個標題client >>> config.remove_section('client') True 刪除標題mysqld下的key_buffer和thread_cache_size >>> config.remove_option('mysqld','key_buffer') True >>> config.remove_option('mysqld','thread_cache_size') True #添加一個標題 >>> config.add_section('mysql') #在標題mysqld下添加read_buffer_size=2M,thread_concurrency=8的配置 >>> config.set('mysqld','read_buffer_size','2M') >>> config.set('mysqld','thread_concurrency','8') #最後將修改的內容寫入文件,完成最終的修改 >>> config.write(open('my.cnf','w'))
>>> 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' >>> with open('example.ini', 'w') as configfile: ... config.write(configfile) ...
十 hashlib模塊
hash:一種算法 ,3.x裏代替了md5模塊和sha模塊,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
三個特色:
>>> import hashlib >>> m = hashlib.md5() # m = hashlib.sha256() >>> m.update('hello'.encode('utf-8')) >>> print(m.digest()) #2進制格式hash b']A@*\xbcK*v\xb9q\x9d\x91\x10\x17\xc5\x92' >>> print(m.hexdigest()) #16進制格式hash 5d41402abc4b2a76b9719d911017c592 >>> m.update('alvin'.encode('utf8')) >>> print(m.hexdigest()) 92a7e713c30abbb0319fa07da2a5c4af >>> m2=hashlib.md5() >>> m2.update('helloalvin'.encode('utf8')) >>> print(m2.hexdigest()) 92a7e713c30abbb0319fa07da2a5c4af ''' 注意:把一段很長的數據update屢次,與一次update這段長數據,獲得的結果同樣,可是update屢次爲校驗大文件提供了可能。 '''
以上加密算法雖然依然很是厲害,但時候存在缺陷,即:經過撞庫能夠反解。因此,有必要對加密算法中添加自定義key再來作加密。
>>> import hashlib ######## 256 ######### >>> hash = hashlib.sha256('898oaFs09f'.encode('utf8')) >>> hash.update('alvin'.encode('utf8')) >>> print (hash.hexdigest()) e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7
import hashlib passwds=[ 'alex3714', 'alex1313', 'alex94139413', 'alex123456', '123456alex', 'a123lex', ] def make_passwd_dic(passwds): dic={} for passwd in passwds: m=hashlib.md5() m.update(passwd.encode('utf-8')) dic[passwd]=m.hexdigest() return dic def break_code(cryptograph,passwd_dic): for k,v in passwd_dic.items(): if v == cryptograph: print('密碼是===>\033[46m%s\033[0m' %k) cryptograph='aee949757a2e698417463d47acac93df' break_code(cryptograph,make_passwd_dic(passwds))
python 還有一個 hmac 模塊,它內部對咱們建立 key 和 內容 進行進一步的處理而後再加密
>>> import hmac >>> h = hmac.new(b'898oaFs09f','alvin'.encode('utf8')) >>> h.update('hello'.encode('utf8')) >>> print (h.hexdigest()) 6b1bc37749ebe91b01e07685221d38ef
#要想保證hmac最終結果一致,必須保證: #1:hmac.new括號內指定的初始key同樣 #2:不管update多少次,校驗的內容累加到一塊兒是同樣的內容 >>> import hmac >>> h1=hmac.new(b'egon') >>> h1.update(b'hello') >>> h1.update(b'world') >>> print(h1.hexdigest()) f1bf38d054691688f89dcd34ac3c27f2 >>> h2=hmac.new(b'egon') >>> h2.update(b'helloworld') >>> print(h2.hexdigest()) f1bf38d054691688f89dcd34ac3c27f2 >>> h3=hmac.new(b'egonhelloworld') >>> print(h3.hexdigest()) bcca84edd9eeb86f30539922b28f3981
十一 subprocess模塊
經常使用subprocess方法示例
>>> import subprocess #執行命令,返回命令執行狀態 , 0 or 非0 >>> retcode = subprocess.call('ls -l',shell=True) #shell = True ,容許 shell 命令是字符串形式 total 20 -rw-r--r-- 1 root root 20480 Nov 1 14:13 tmp_file.tar >>> print(retcode) 0 >>> retcode = subprocess.call('aaa',shell=True) #若是輸入一個錯誤的命令,Python解釋器不會提示任何信息 /bin/sh: aaa: command not found #這裏是系統執行命令返回的系統報錯 >>> print(retcode) 127 #執行命令,若是命令結果爲0,就正常返回,不然拋異常 >>> subprocess.check_call('ls -l',shell=True) total 20 -rw-r--r-- 1 root root 20480 Nov 1 14:13 tmp_file.tar 0 >>> subprocess.check_call('aaa',shell=True) /bin/sh: aaa: command not found #這裏是系統執行命令返回的系統報錯 Traceback (most recent call last): #這裏是Python解釋器返回的報錯 File "<stdin>", line 1, in <module> File "/usr/local/python3/lib/python3.6/subprocess.py", line 291, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command 'aaa' returned non-zero exit status 127. #接收字符串格式命令,返回元組形式,第1個元素是執行狀態,第2個是命令結果 >>> subprocess.getstatusoutput('ls /bin/ls') (0, '/bin/ls') #接收字符串格式命令,並返回結果 >>> subprocess.getoutput('ls /bin/ls') '/bin/ls' #執行命令,並返回結果,注意是返回結果,不是打印,下例結果返回給res >>> res=subprocess.check_output('ls -l',shell=True) >>> res b'total 20\n-rw-r--r-- 1 root root 20480 Nov 1 14:13 tmp_file.tar\n' ##上面那些方法,底層都是封裝的subprocess.Popen poll() Check if child process has terminated. Returns returncode wait() Wait for child process to terminate. Returns returncode attribute. terminate() 殺掉所啓動進程 communicate() 等待任務結束 stdin 標準輸入 stdout 標準輸出 stderr 標準錯誤 pid The process ID of the child process. #例子 >>> p = subprocess.Popen('df -h | grep sdb1',stdin=subprocess.PIPE,stdout=subprocess.PIPE,shell=True) >>> p.stdout.read() b'/dev/sdb1 4.8G 20M 4.6G 1% /usr/local/mysql/data\n'
subprocess.run(...)
>>> subprocess.run('ls -l',shell=True) total 20 -rw-r--r-- 1 root root 20480 Nov 1 14:13 tmp_file.tar CompletedProcess(args='ls -l', returncode=0) >>> subprocess.run('exit 1', shell=True, check=True) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/python3/lib/python3.6/subprocess.py", line 418, in run output=stdout, stderr=stderr) subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1. >>> subprocess.run('ls -l /dev/null',shell=True,stdout=subprocess.PIPE) CompletedProcess(args='ls -l /dev/null', returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3 Nov 2 09:48 /dev/null\n')
調用subprocess.run(...)是推薦的經常使用方法,在大多數狀況下能知足需求,但若是你可能須要進行一些複雜的與系統的交互的話,你還能夠用subprocess.Popen(),語法以下:
>>> p = subprocess.Popen('ping -c5 127.0.0.1',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) >>> print(p.stdout.read())
可用參數:
因此不能將close_fds設置爲True同時重定向子進程的標準輸入、輸出與錯誤(stdin, stdout, stderr)。
將被傳遞給底層的CreateProcess()函數,用於設置子進程的一些屬性,如:主窗口的外觀,進程的優先級等等
終端輸入的命令分爲兩種:
須要交互的命令示例
十二 logging模塊
不少程序都有記錄日誌的需求,而且日誌中包含的信息即有正常的程序訪問日誌,還可能有錯誤、警告等信息輸出。Python的logging模塊提供了標準的日誌接口,能夠經過它存儲各類格式的日誌,logging的日誌能夠分爲5個級別:
說明:
最簡單的日誌輸出,默認打印到終端
>>> import logging >>> logging.debug('This is a debug log.') >>> logging.info('This is a info log.') >>> logging.warning('This is a warning log.') WARNING:root:This is a warning log. >>> logging.error('This is a error log.') ERROR:root:This is a error log. >>> logging.critical('This is a critical log.') CRITICAL:root:This is a critical log. ''' 爲何前面兩條日誌沒有被打印出來??? 這是由於logging模塊提供的日誌記錄函數所使用的日誌器設置的日誌級別是WARNING,所以只有WARNING級別的日誌記錄以及大於它的ERROR和CRITICAL級別的 日誌記錄被輸出了,而小於它的DEBUG和INFO級別的日誌記錄被丟棄了。 '''
把日誌寫到文件裏
>>> import logging >>> logging.basicConfig(filename=r'd:\access.log', format="%(asctime)s [%(filename)s:%(lineno)d] %(levelname)s %(message)s", datefmt='%Y-%m-%d %H:%M:%S %p', level=logging.INFO) >>> logging.debug('調試debug') >>> logging.info('消息info') >>> logging.warning('警告warn') >>> logging.error('錯誤error') >>> logging.critical('嚴重critical') #access.log內容: 2017-11-15 14:15:09 [<pyshell#7>:2] INFO 消息info 2017-11-15 14:15:32 [<pyshell#8>:2] WARNING 警告warn 2017-11-15 14:16:15 [<pyshell#9>:2] ERROR 錯誤error 2017-11-15 14:16:55 [<pyshell#10>:2] CRITICAL 嚴重critical
可在logging.basicConfig()函數中可經過具體參數來更改logging模塊默認行爲,可用參數有:
format參數中可能用到的格式化串
%(asctime)s 日誌事件發生的時間--人類可讀時間,默認格式是 「2003-07-08 16:49:45,896」。逗號後面的是毫秒 %(created)f 日誌事件發生的時間--時間戳,就是當時調用time.time()函數返回的值 %(relativeCreated)d 日誌事件發生的時間相對於logging模塊加載時間的相對毫秒數(通常不用) %(msecs)d 日誌事件發生事件的毫秒部分 %(levelname)s 該日誌記錄的文字形式的日誌級別('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL') %(levelno)s 該日誌記錄的數字形式的日誌級別(10, 20, 30, 40, 50) %(name)s 所使用的日誌器名稱,默認是'root',由於默認使用的是 rootLogger %(message)s 用戶輸出的消息 %(pathname)s 調用日誌輸出函數的模塊的完整路徑名,可能沒有 %(filename)s 調用日誌輸出函數的模塊的文件名,包含文件後綴 %(module)s 調用日誌輸出函數的模塊名,不包含後綴 %(lineno)d 調用日誌輸出函數的語句所在的代碼行 %(funcName)s 調用日誌輸出函數的函數名 %(process)d 進程ID。可能沒有 %(processName)s 進程名稱,Python 3.1新增 %(thread)d 線程ID。可能沒有 %(threadName)s 線程名。可能沒有
若是想同時把LOG打印到屏幕和文件日誌裏,可使用logging模塊提供的四個主要類來實現:
Logger類 每一個程序在輸出信息以前都要得到一個Logger。Logger一般對應了程序的模塊名,好比聊天工具的圖形界面模塊能夠這樣得到它的Logger: LOG=logging.getLogger(」chat.gui」) 而核心模塊能夠這樣: LOG=logging.getLogger(」chat.kernel」) Logger.setLevel(lel):指定最低的日誌級別,低於lel的級別將被忽略。debug是最低的內置級別,critical爲最高 Logger.addFilter(filt)、Logger.removeFilter(filt):添加或刪除指定的filter Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增長或刪除指定的handler Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():能夠設置的日誌級別 Handler類 handler對象負責發送相關的信息到指定目的地。Python的日誌系統有多種Handler可使用。有些Handler能夠把信息輸出到控制檯,有些Logger能夠把信息輸出到文件,還有些 Handler能夠把信息發送到網絡上。若是以爲不夠用,還能夠編寫本身的Handler。能夠經過addHandler()方法添加多個多handler Handler.setLevel(lel):指定被處理的信息級別,低於lel級別的信息將被忽略 Handler.setFormatter():給這個handler選擇一個格式 Handler.addFilter(filt)、Handler.removeFilter(filt):新增或刪除一個filter對象 每一個Logger能夠附加多個Handler。接下來咱們就來介紹一些經常使用的Handler: 1) logging.StreamHandler 使用這個Handler能夠向相似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息。它的構造函數是: StreamHandler([strm]) 其中strm參數是一個文件對象。默認是sys.stderr 2) logging.FileHandler 和StreamHandler相似,用於向一個文件輸出日誌信息。不過FileHandler會幫你打開這個文件。它的構造函數是: FileHandler(filename[,mode]) filename是文件名,必須指定一個文件名。 mode是文件的打開方式。參見Python內置函數open()的用法。默認是’a',即添加到文件末尾。 3) logging.handlers.RotatingFileHandler 這個Handler相似於上面的FileHandler,可是它能夠管理文件大小。當文件達到必定大小以後,它會自動將當前日誌文件更名,而後建立 一個新的同名日誌文件繼續輸出。好比日誌文件是chat.log。當chat.log達到指定的大小以後,RotatingFileHandler自動把 文件更名爲chat.log.1。不過,若是chat.log.1已經存在,會先把chat.log.1重命名爲chat.log.2。。。最後從新建立 chat.log,繼續輸出日誌信息。它的構造函數是: RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]]) 其中filename和mode兩個參數和FileHandler同樣。 maxBytes用於指定日誌文件的最大文件大小。若是maxBytes爲0,意味着日誌文件能夠無限大,這時上面描述的重命名過程就不會發生。 backupCount用於指定保留的備份文件的個數。好比,若是指定爲2,當上面描述的重命名過程發生時,原有的chat.log.2並不會被改名,而是被刪除。 4) logging.handlers.TimedRotatingFileHandler 這個Handler和RotatingFileHandler相似,不過,它沒有經過判斷文件大小來決定什麼時候從新建立日誌文件,而是間隔必定時間就 自動建立新的日誌文件。重命名的過程與RotatingFileHandler相似,不過新的文件不是附加數字,而是當前時間。它的構造函數是: TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]]) 其中filename參數和backupCount參數和RotatingFileHandler具備相同的意義。 interval是時間間隔。 when參數是一個字符串。表示時間間隔的單位,不區分大小寫。它有如下取值: S 秒 M 分 H 小時 D 天 W 每星期(interval==0時表明星期一) midnight 天天凌晨 5) logging.handlers.HTTPHandler 將日誌消息以GET或POST的方式發送給一個HTTP服務器 6) logging.handlers.SMTPHandler 將日誌消息發送給一個指定的email地址 7) logging.NullHandler 該Handler實例會忽略error messages,一般被想使用logging的library開發者使用來避免'No handlers could be found for logger XXX'信息的出現。 Filter類 Filter能夠被Handler和Logger用來作比level更細粒度的、更復雜的過濾功能。Filter是一個過濾器基類,它只容許某個logger層級下的日誌事件經過過濾。該類定義以下: class logging.Filter(name='') filter(record) 好比,一個filter實例化時傳遞的name參數值爲'A.B',那麼該filter實例將只容許名稱爲相似以下規則的loggers產生的日誌記錄經過過濾:'A.B','A.B,C','A.B.C.D','A.B.D',而名稱爲'A.BB', 'B.A.B'的loggers產生的日誌則會被過濾掉。若是name的值爲空字符串,則容許全部的日誌事件經過過濾。 filter方法用於具體控制傳遞的record記錄是否能經過過濾,若是該方法返回值爲0表示不能經過過濾,返回值爲非0表示能夠經過過濾。 Formater類 Formater對象用於配置日誌信息的最終順序、結構和內容。與logging.Handler基類不一樣的是,應用代碼能夠直接實例化Formatter類。另外,若是你的應用程序須要一些特殊的處理行爲,也能夠實現一個Formatter的子類來完成。 Formatter類的構造方法定義以下: logging.Formatter.__init__(fmt=None, datefmt=None, style='%')
logging模塊就是經過這些組件來完成日誌處理的,上面所使用的logging模塊級別的函數也是經過這些組件對應的類來實現的
這些組件之間的關係描述:
簡單點說就是:日誌器(logger)是入口,真正幹活兒的是處理器(handler),處理器(handler)還能夠經過過濾器(filter)和格式器(formatter)對要輸出的日誌內容作過濾和格式化等處理操做。
>>> import logging >>> from logging.handlers import RotatingFileHandler # 建立一個日誌器logger並設置其日誌級別爲WARNING >>> logger = logging.getLogger('LOG') >>> logger.setLevel(logging.WARNING) # 建立一個流處理器ch_handler並設置其日誌級別爲DEBUG,還建立一個格式器 >>> ch_handler = logging.StreamHandler() >>> ch_handler.setLevel(logging.DEBUG) >>> ch_formatter = logging.Formatter("%(asctime)s [%(filename)s:%(lineno)d] %(levelname)s %(message)s", datefmt='%Y-%m-%d %H:%M:%S %p') # 建立一個文件處理器fh_handler並設置其日誌級別爲INFO,還建立一個格式器 >>> fh_handler = RotatingFileHandler(r'd:\log_test.log',maxBytes=20*1024*1024,backupCount=10) >>> fh_handler.setLevel(logging.INFO) >>> fh_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") # 將流格式器添加處處理器ch_handler >>> ch_handler.setFormatter(ch_formatter) # 將文件格式器添加處處理器fh_handler >>> fh_handler.setFormatter(fh_formatter) #添加ch_handler和fh_handler處理器到日誌器logger >>> logger.addHandler(ch_handler) >>> logger.addHandler(fh_handler) #屏幕輸出 >>> logger.debug('debug message') >>> logger.info('info message') >>> logger.warn('warn message') 2017-11-16 15:37:03 PM [<pyshell#26>:2] WARNING warn message >>> logger.error('error message') 2017-11-16 15:37:20 PM [<pyshell#27>:2] ERROR error message >>> logger.critical('critical message') 2017-11-16 15:37:27 PM [<pyshell#28>:2] CRITICAL critical message # log_test.log文件內容: 2017-11-16 15:37:03,055 - LOG - WARNING - warn message 2017-11-16 15:37:20,433 - LOG - ERROR - error message 2017-11-16 15:37:27,371 - LOG - CRITICAL - critical message
十三 re模塊
經常使用匹配模式(元字符)
'\w' 匹配字母數字及下劃線 '\W' 匹配非字母數字下劃線 '\s' 匹配任意空白字符,等價於 [\t\n\r\f] '\S' 匹配任意非空字符 '\d' 匹配任意數字,等價於 [0-9] '\D' 匹配任意非數字 '\A' 匹配字符串開始 '\Z' 匹配字符串結束,若是是存在換行,只匹配到換行前的結束字符串 '\z' 匹配字符串結束 '\G' 匹配最後匹配完成的位置 '\n' 匹配一個換行符 '\t' 匹配一個製表符 '^' 匹配字符串的開頭 '$' 匹配字符串的末尾 '.' 默認匹配除換行符(\n)之外的任意字符,若指定flag DOTALL,則能夠匹配包括換行符的任意字符 '[...]' 用來表示一組字符,單獨列出:[amk]匹配'a','m'或'k' '[^...]' 不在[]中的字符:[^abc]匹配除了a,b,c以外的字符。 '*' 匹配前一個字符或表達式0次或屢次 '+' 匹配前一個字符或表達式1次或屢次 '?' 匹配前一個字符或表達式1次或0次,非貪婪方式 '{n}' 精確匹配前一個字符或表達式n次 '{n,m}' 匹配前一個字符或表達式n次到m次,貪婪模式 'a|b' 匹配a或者b '()' 匹配括號內的表達式,也表示一個
re.search()
掃描整個字符串,只到找到第一個匹配而後返回一個包含匹配信息的對象,該對象能夠經過調用group()方法獲得匹配的字符串,若是字符串沒有匹配,則返回None。
語法格式:
re.search(pattern,string,flags=0)
>>> import re #常規匹配 >>> result = re.search('he','hi! hello world,good') >>> print(result) <_sre.SRE_Match object at 0x020E6058> >>> print(result.group()) #獲取匹配的結果 he >>> print(result.span()) #獲取匹配字符串的長度範圍 (4, 6) # ()匹配目標 >>> import re >>> result = re.search('\w+\s(\w*)','hi! hello world,good') #爲了匹配字符串中具體的目標,則須要經過()括起來 >>> result.group() 'hello world' >>> result.group(1) #獲取第一個括號中匹配的結果 'world' >>> result.groups() #返回的是一個元組形式 ('world',) # .*貪婪匹配 >>> import re >>> result = re.search('he.*(\d+).*','hi! hello 123456 world') >>> result.group(1) '6' ''' 從結果中能夠看出只匹配到了6,並無匹配到123456,出現這種狀況的緣由是前面的.* 給匹配掉了, .*在這裏會儘量的匹配多的內容,也就是咱們所說的貪婪匹配 ''' #若是想要匹配到123456,能夠把正則表達式改成: >>> result = re.search('he.*?(\d+).*','hi! hello 123456 world') # re.S匹配模式 >>> content = """hi! hello 123456 world my name is tbb """ >>> result = re.search('he.*?(\d+).*?tbb$',content,re.S) #用匹配模式re.S來匹配換行的內容 >>> result.group() 'hello 123456 world\nmy name is tbb' >>> print(result.group()) hello 123456 world my name is tbb >>> print(result.group(1)) 123456 # \轉義 >>> import re >>> content = 'hello! price is $5.00' >>> result = re.search('price is \$5\.00',content) >>> print(result.group()) price is $5.00 #若是要匹配\,可使用以下方法: >>> re.search(r'a\\c','a\c').group() #r表明告訴解釋器使用rawstring,即原生字符串,把咱們正則內的全部符號都當普通字符處理,不要轉義 'a\\c' 或 >>> re.search('a\\\\c','a\c').group() 'a\\c' ''' 當咱們要匹配的內容中存在特殊字符的時候,就須要用到轉移符號\ '''
re.match()
嘗試從字符串的起始位置匹配一個模式,若是不是起始位置匹配的話,match()就會返回None
同search,不過在字符串開始處進行匹配,徹底能夠用search+^代替match,以下所示:
>>> result = re.match('world','hello world') >>> print(result) None >>> result = re.search('world','hello world') >>> print(result) <_sre.SRE_Match object; span=(6, 11), match='world'> >>> result = re.search('^world','hello world') >>> print(result) None
re.findall()
搜索字符串,以列表的形式返回所有能匹配的子串
>>> re.findall('a[+*(]b','a*b a+b a-b a=b') ['a*b', 'a+b']
re.split()
>>> re.split('[ab]','abcd') #先按'a'分割獲得''和'bcd',再對''和'bcd'分別按'b'分割 ['', '', 'cd']
re.sub()
替換字符串中每個匹配的子串後返回替換後的字符串
re.sub(正則表達式,替換成的字符串,原字符串)
>>> re.sub('l','L','hello world') #不指定n,默認替換全部 'heLLo worLd' >>> re.sub('l','L','hello world',1) 'heLlo world' >>> re.sub('l','L','hello world',2) 'heLLo world' >>> re.sub('(\d+)',r'\1 7890','hello 123456 world') #獲取匹配的字符串後面添加些內容,\1是獲取第一個匹配的結果。爲了防止轉義字符的問題,須要在前面加上r 'hello 123456 7890 world' >>> re.sub('(\w*)(\s*)(\d+)(\s*)(\w*)',r'\5\4\3\2\1','hello 123456 world') #把匹配到的結果按照順序對原有字符串進行組合,返回新的字符串 'world 123456 hello' >>> re.subn('l','L','hello world') #結果帶有總共替換的個數 ('heLLo worLd', 3)
re.compile()
將正則表達式編譯成正則表達式對象,方便複用該正則表達式
>>> content = 'hello 123456 world' >>> obj = re.compile('\d{3}') >>> obj.search(content).group() '123' >>> obj.findall(content) #重用了obj ['123', '456']
對上面的一個小結:儘可能使用泛匹配,使用括號獲得匹配目標,儘可能使用非貪婪模式,有換行符就用re.S強調re.match是從字符串的起始位置匹配一個模式