1、random模塊python
(0, 1):random.random() [1, 10]:random.randint(1, 10) [1, 10):random.randrange(1, 10) (1, 10):random.uniform(1, 10) 單例集合隨機選擇1個:random.choice(item) 單例集合隨機選擇n個:random.sample(item, n) 洗牌單列集合:random.shuffle(item)
import random #模塊地址 print(random) # <module 'random' from 'F:\\安裝包\\Python36\\lib\\random.py'> #random.random()取值範圍0-1之間的小數,不包含0和1 for i in range(2): print(random.random()) #(0,1) #取值0-2之間,可是random.random()輸出的值都是0-1之間 #0.6179348878875671 #0.7546476092920288 #random.randint() 取值範圍[1,5]:包含1和5 for i in range(5): print(random.randint(1,5)) #[1,5] # random.randrange() #[1,5)取值範圍1-4,不包含5 for i in range(5): print(random.randrange(1,5)) #[1,4] # random.uniform() 取值範圍(1,5)之間的小數 for i in range(5): print(random.uniform(1,5)) #小數:(1,5) # print('%.3f' % random.uniform(1,5)) #%f 能夠定義取值的長度 %.3f取3位小數 #洗牌單列集合:random.shuffle(item) ls = [1,2,3,4,5] print(random.shuffle(ls)) #None print(ls) #對ls隨機排序[4, 5, 2, 3, 1] #單例集合隨機選擇1個:random.choice(item) print(random.choice(ls)) # 隨機輸出ls中一個值 #單例集合隨機選擇n個:random.sample(item, n) print(random.sample(ls,3)) # [2, 4, 3] 不會同時出現2個同樣的數字
練習:驗證碼功能
# 方法一 # count驗證碼位數,根據需求出幾位 import random def get_code(count): code = "" # 能產生大小寫字母和數字 # 進行字符串拼接 for i in range(count): c1 = chr(random.randint(65,90)) #(65,90) ascii表對應大寫字母,chr對應數字轉換爲字母 c2 = chr(random.randint(97,122)) #(97,122) ascii表對應小寫字母 c3 = str(random.randint(0,9)) # 數字 code += random.choice([c1,c2,c3]) return code print(get_code(4)) # 方法二:效率高,只須要循環2個,但邏輯多 def get_code(count): code = "" for i in range(count): r = random.choice([1,2 ,3]) if r == 1: c = chr(random.randint(65,90)) elif r == 2: c = chr(random.randint(97,122)) else: c = str(random.randint(0,9)) code += c return code print(get_code(6)) # d7H7C3 # 第3中方法:將全部字母數字的選項都寫在一塊兒,每次選中都不會重複 def get_code(count): target = "1234567890QWERTYUIOPASDFGHJKLZXCVBNMwqertiuopadsfklzvcxbnm" code_list = random.sample(target,count) return ''.join(code_list) #3PqXiR82 return code_list #['p', '1', 'S', '9', 'c', 's', 'k', 'A'] print(get_code(18)) #Kv47ZiznkPD0eO3I5d
2、序列化模塊正則表達式
# 什麼是序列化:將對象轉化爲字符串 # 什麼是反序列化:將字符串轉化爲對象 # 爲何要序列化:數據的存儲和傳輸都採用的是字符串類型 # 序列化的模塊:json pickle shelve # json:支持跨語言,用於數據的傳輸 # pickle:支持py的全部數據類型,全部能夠將全部py的對象序列化後存儲 # shelve:支持py的全部數據類型,能夠即時存與取 # 序列化 dump dumps # 反序列化 load loads
三.Json模塊:用於傳輸(多語言支持)shell
什麼是json:就是完成文本序列化獲得的文本字符串,json字符串具備必定的語法規範 1.支持的數據類型:int float str bool dict list null # json中布爾類型轉換爲小寫,不支持set 和tuple 2.複雜的json都是由{}與[]嵌套造成的數據 3.json字符串只能有一個根: json_str = '{}{}' | '{}[]' | '[][]' | '1null' # 報錯,都是兩個根 4.json中的str類型必須用""包裹(json字符串中的字符串類型不支持'' """""")
import json # python對象 序列化 json字符串 data = None res = json.dumps(data) print(res) # json字符串 反序列化 python對象 json_str = '3.14' json_str = 'true' json_str = 'null' json_str = '{}' json_str = '[]' json_str = '1, null' # 有誤,兩個根 json_str = "\"abc\"" #反序列化去引號 json_str = '"abc"' obj = json.loads(json_str) print(obj, type(obj))
操做文件:讀()存與寫(取)
# 序列化 obj = {'name': 'Simon', 'age': 17, 'gender': '男'} with open('a.txt', 'w', encoding='utf-8') as wf: json.dump(obj, wf, ensure_ascii=False) # ensure_ascii 默認爲True ansci碼;#False跟隨文件編碼utf-8 # json.dump(obj, wf) #{"name": "Simon", "age": 17, "gender": "男"}{"name": "Simon", "age": 17, "gender": "\u7537"} # 文件內容123456:由於wf文件只打開一次,打開的時候操做一次,以後都是寫 # wf.write('123') # wf.write('456') # 反序列化 with open('a.txt', 'r', encoding='utf-8') as rf: obj = json.load(rf) print(obj) # {'name': 'Simon', 'age': 17, 'gender': '男'} # 注:json模塊的序列化與反序列化是一一對應關係 print(json.load(open('a.txt', 'r', encoding='utf-8'))) # {'name': 'Simon', 'age': 17, 'gender': '男'}
4、 pickle模塊:支持全部數據類型(不支持其餘語言,只用於python)編程
import pickle obj = {'name': 'simon', 'age': 17, 'gender': '男'} res = pickle.dumps(obj) print(res) # b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x05\x00\x00\x00simonq\x02X\x03\x00\x00\x00ageq\x03K\x11X\x06\x00\x00\x00genderq\x04X\x03\x00\x00\x00\xe7\x94\xb7q\x05u.' pickle.dump(obj,open('b.txt','wb')) #內容: �}q (X nameqX simonqX ageqKX genderqX 男qu. # 反序列化 print(pickle.loads(res)) # {'name': 'simon', 'age': 17, 'gender': '男'} print(pickle.load(open('b.txt', 'rb'))) # {'name': 'simon', 'age': 17, 'gender': '男'}
5、shelve模塊:支持全部數據類型(優化存與取的方式)json
# shelve將dump與load封裝爲一步 import shelve # 將文件的方法封裝到模塊中,文件後綴本身隨便取的 #新建了3個文件:c.shv.bak c.shv.dat c.shv.dir shv_tool = shelve.open('c.shv') # 序列化 # shv_tool['name'] = 'Simon' # 反序列化 res = shv_tool['name'] print(res) # Simon shv_tool.close() # 文件經過shelve對象來關閉,關閉後就不能再取,不然就報錯 # 二次操做:從新打開與關閉 shv_tool = shelve.open('c.shv') print(shv_tool['name']) # Simon shv_tool.close() # 操做方式 with shelve.open('c.shv') as shv_tool: print(shv_tool['name']) # Simon # writeback將反序列化到內存的數據,操做後即時同步到文件中 with shelve.open('c.shv', writeback=True) as shv_tool: shv_tool['stus'] = ['Bob', 'Tom'] # 重置 # print(shv_tool['stus']) # ['Bob', 'Tom'] shv_tool['stus'].append('Jobs') # 將數據取到內存,在內存中添加 print(shv_tool['stus']) # ['Bob', 'Tom', 'Jobs']
6、shutil:能夠操做權限的處理文件模塊windows
import shutil # 基於路徑的文件複製: shutil.copyfile('source_file', 'target_file') # 絕對路徑:複製後的文件名是須要的 shutil.copyfile(r'C:\shelev.py',r'D:\target.py') # 基於流的文件複製: with open('source_file', 'rb') as r, open('target_file', 'wb') as w: shutil.copyfileobj(r, w) # 遞歸刪除目標目錄:目錄裏有文件也直接刪除 shutil.rmtree('target_folder') # 文件移動 shutil.remove('old_file', 'new_file') # 文件夾壓縮 # file_name: 壓縮後獲得的文件名 format:壓縮格式 archive_path:要壓縮的文件夾路徑 shutil.make_archive('file_name', 'format', 'archive_path') # 舉例 shutil.make_archive('target/abc', 'zip', 'source') #在target 目錄中將source目錄壓縮到target目錄中名爲abc.zip # 文件夾解壓 # unpack_file: 解壓的文件 unpack_name:解壓獲得的文件夾名 format:解壓格式 shutil.unpack_archive('unpack_file', 'unpack_name', 'format') # 舉例 shutil.unpack_archive('target/abc.zip', 'target/xyz', 'zip') #將abc.zip解壓爲xyz文件夾
7、加密模塊app
# 通常加密解密方法: # md5加密:不可逆加密 # 碰撞解密:用數據再進行一次加密,與原加密結果作匹配
hashlib模塊加密dom
import hashlib data = '數據' # 生成對象 lock_obj = hashlib.md5(data.encode('utf-8')) # 生產加密鎖對象,傳入加密數據 result = lock_obj.hexdigest() # 獲取加密後的加密串 print(result) # update能夠往鎖對象中添加加密數據 lock_obj = hashlib.md5() lock_obj.update(b'123') lock_obj.update(b'abc') lock_obj.update('嘿嘿'.encode('utf-8')) print(lock_obj.hexdigest()) lock_obj.update(b'000') print(lock_obj.hexdigest()) # 000 | '123abc嘿嘿000'.encode('utf-8') print(hashlib.md5('123abc嘿嘿000'.encode('utf-8')).hexdigest()) # 注:要爲新數據提供加密,必定要爲該數據建立一個加密對象
# 加鹽:前提是支持update # 什麼是加鹽:在原數據前或後添加一些預約的數據,與原數據一塊兒進行加密 # 爲何要加鹽: # 1.當原數據過於簡單,能夠對其加鹽,提升數據的複雜度 # 2.鹽與數據有必定類似度,混淆對真實數據的提取 data = 'ab_12' lock_obj = hashlib.md5() lock_obj.update(b'a12_d') lock_obj.update(data.encode('utf-8')) lock_obj.update(b'dd_121') print(lock_obj.hexdigest()) # a12_dab_12dd_121在數據先後加鹽混淆 # 其餘位數加密 lock_obj = hashlib.sha3_256(b'123') print(lock_obj.hexdigest()) lock_obj = hashlib.sha3_512(b'123') lock_obj.update(b'salt') print(lock_obj.hexdigest())
hmac模塊加密編程語言
import hmac # 與hashlib的不一樣點:生產鎖對象時必須提升數據參數 lock_obj = hmac.new(b'') print(lock_obj.hexdigest())
# 支持加鹽 lock_obj = hmac.new(b'') lock_obj.update(b'salt') print(lock_obj.hexdigest())
8、logging:日誌模塊ide
# logging記錄項目日誌的模塊 # 記錄日誌:將項目中產生的一些數據,或是信息,或是錯誤再也不輸出到控制檯,而是輸出到文件中,保存這樣信息的文件就稱之爲日誌文件
# 日誌級別 在開始記錄日誌前還須要明確,日誌的級別 隨着時間的推移,日誌記錄會很是多,成千上萬行,如何快速找到須要的日誌記錄這就成了問題 解決的方案就是 給日誌劃分級別 logging模塊將日誌分爲了五個級別,從高到低分別是: 1.info 常規信息 2.debug 調試信息 3.warning 警告信息(默認級別) 4.error 錯誤信息 5.cretical 嚴重錯誤 本質上他們使用數字來表示級別的,從高到低分別是10,20,30,40,50
#1.導入模塊 import logging #2.輸出日誌 logging.info("info") logging.debug("debug調試") logging.warning("warning警告") logging.error("error錯誤") logging.critical("critical嚴重錯誤") # 輸出 WARNING:root:warning # 輸出 ERROR:root:error # 輸出 CRITICAL:root:critical
1.logging模塊的基本配置使用:
import logging import sys # 2.日誌的基本配置 logging.basicConfig( # 輸出級別 level=logging.INFO, # level=10, # 輸出位置 # stream=sys.stderr, # sys.stdout 往控制檯輸出 filename='log/my.log', # 往文件輸出 => 若是須要同時往多個位置輸出,須要handles # 輸出格式 format='%(asctime)s[%(name)s]: %(msg)s', datefmt='%Y-%m-%d %H:%M:%S' )
# my.log日誌:2019-05-16 14:39:32[root]: error msg # 標準輸入 # print(sys.stdin.readline())
# filename:用指定的文件名建立FiledHandler(後邊會具體講解handler的概念),這樣日誌會被存儲在指定的文件中。 # filemode:文件打開方式,在指定了filename時使用這個參數,默認值爲「a」還可指定爲「w」。 # format:指定handler使用的日誌顯示格式。 # datefmt:指定日期時間格式。 # level:設置rootlogger(後邊會講解具體概念)的日誌級別 #案例: logging.basicConfig( filename="aaa.log", filemode="at", datefmt="%Y-%m-%d %H:%M:%S %p", format="%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s", level=10 )
格式化所有可用名稱:
%(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:用戶輸出的消息
2.logging的成員組成
logging模塊的四個核心角色: 1.Logger 日誌生成器 產生日誌 2.Filter 日誌過濾器 過濾日誌 3.Handler 日誌處理器 對日誌進行格式化,並輸出到指定位置(控制檯或文件) 4.Formater 處理日誌的格式
import logging # 1.打印者:自定義的打印者如何配置 log1 = logging.getLogger('logger name') # 2.輸出位置:兩個文件輸出位置與一個控制檯輸出位置 hd_a = logging.FileHandler('log/a.log', encoding='utf-8') hd_cmd = logging.StreamHandler() # 3.輸出格式 fmt1 = logging.Formatter('%(asctime)s 【%(name)s】- %(msg)s') fmt2 = logging.Formatter('%(asctime)s - %(msg)s') # 4.打印者添加句柄 - 設置打印者的輸出位置 log1.addHandler(hd_a) log1.addHandler(hd_cmd) # 5.將格式綁定給輸出位置(句柄) hd_a.setFormatter(fmt1) hd_cmd.setFormatter(fmt2) # 6.權限控制 log1.setLevel(logging.DEBUG) # 打印者規定打印級別 hd_a.setLevel(logging.WARNING) # 不一樣輸出位置(句柄)再能夠二次限定輸出級別 hd_cmd.setLevel(logging.DEBUG) # 不一樣輸出位置(句柄)再能夠二次限定輸出級別 # 7.不一樣級別輸出信息 log1.debug('debug msg') log1.info('info msg') log1.warning('warning msg') log1.error('error msg') log1.critical('critical msg')
import logging # root打印者,用logging.basicConfig來配置 # logging.critical('12345') # 1.打印者:自定義的打印者如何配置 log1 = logging.getLogger('Owen') # log1.critical('67890') log2 = logging.getLogger('Simon') # log2.critical('00000') # 2.輸出位置:兩個文件輸出位置與一個控制檯輸出位置 hd_a = logging.FileHandler('log/a.log', encoding='utf-8') hd_b = logging.FileHandler('log/b.log', encoding='utf-8') hd_cmd = logging.StreamHandler() #控制檯輸出 # )) 爲輸出者綁定輸出位置 log1.addHandler(hd_a) log1.addHandler(hd_b) log2.addHandler(hd_b) log2.addHandler(hd_cmd) # 3.輸出格式 fmt1 = logging.Formatter('%(asctime)s 【%(name)s】- %(msg)s') fmt2 = logging.Formatter('%(asctime)s - %(msg)s') # ))將格式綁定給輸出位置(句柄) hd_a.setFormatter(fmt1) hd_b.setFormatter(fmt1) hd_cmd.setFormatter(fmt2) # 級別控制: 打印者規定打印級別,輸出位置(句柄)再能夠二次限定,級別>=打印者級別 log2.setLevel(logging.DEBUG) hd_b.setLevel(logging.WARNING) hd_cmd.setLevel(logging.DEBUG) log2.debug('debug msg') log2.info('info msg') log2.warning('warning msg') log2.error('error msg') log2.critical('critical msg') # 4.輸出 log1.critical('log1 輸出的 critical msg') log2.critical('log2 輸出的 critical msg') # 過濾:少用 # logging.Filter
3.logging配置文件項目開發運用
# 1.將打印者,句柄,與格式封裝成配置信息 # 2.加載配置信息 # 3.使用自定義logger,採用的就是配置信息設置的logger # 優點:1,2兩步是一勞永逸的,後期開發只須要在要記錄日誌的文件中使用自定義logger
# 1、基礎配置:目錄conf/setting.py LOGGING_DIC = { 'version': 1, 'disable_existing_loggers': False, #讓系統的默認配置失效 'formatters': { # 名稱格式定義 'o_fmt1': { 'format': '%(asctime)s 【%(name)s】- %(msg)s' }, 'o_fmt2': { 'format': '%(asctime)s - %(msg)s' } }, 'filters': {}, 'handlers': { 'o_hd_file': { 'level': 'WARNING', 'class': 'logging.handlers.RotatingFileHandler', # 打印到控制檯 'formatter': 'o_fmt1', 'filename': 'log/sys.log', 'encoding': 'utf-8', 'maxBytes': 1024*1024*5, # 日誌大小5M 'backupCount': 5, # 文件切分:寫滿一個就更名爲sys1.log,寫滿5個清空從新記錄 }, 'o_hd_cmd': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 打印到控制檯 'formatter': 'o_fmt2' } }, 'loggers': { 'o_owen': { 'level': 'DEBUG', 'handlers': ['o_hd_file', 'o_hd_cmd'] }, 'o_simon': { 'level': 'DEBUG', 'handlers': ['o_hd_cmd'], # 'propagate': True # 向更高的level logging傳遞 } } } # 2、加載配置 import logging.config logging.config.dictConfig(LOGGING_DIC) # 3、使用 log = logging.getLogger('o_simon') log.critical('信息') log1 = logging.getLogger('o_owen') log1.critical('信息')
# 目錄:lib/common.py from conf.settings import LOGGING_DIC import logging.config logging.config.dictConfig(LOGGING_DIC) def getLogger(name): return logging.getLogger(name)
測試:
from lib.common import getLogger log = getLogger('o_owen') log.debug('12345') log.critical('67890')
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \ '[%(levelname)s][%(message)s]' #其中name爲getlogger指定的名字 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s' logfile_path = "配置文件路徑" LOGGING_DIC = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': standard_format }, 'simple': { 'format': simple_format }, }, 'filters': {}, 'handlers': { #打印到終端的日誌 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 打印到屏幕 'formatter': 'simple' }, #打印到文件的日誌,收集info及以上的日誌 'default': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 'formatter': 'standard', 'filename': logfile_path, # 日誌文件 'maxBytes': 1024*1024*5, # 日誌大小 5M 'backupCount': 5, #日誌文件最大個數 'encoding': 'utf-8', # 日誌文件的編碼 }, }, 'loggers': { #logging.getLogger(__name__)拿到的logger配置 'aa': { 'handlers': ['default', 'console'], # 這裏把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)傳遞 }, # 把key設置爲空 '': { 'handlers': ['default', 'console'], # 這裏把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)傳遞 }, }, }
#lib/common.py #日誌功能 import logging.config from conf import settings # 在lib 文件夾的common文件中生成日誌對象 #生成日誌對象 def get_logger(name): # 先把日誌配置傳給logging logging.config.dictConfig(settings.LOGGING_DIC) # 生產日誌對象--》接收的是name,根據name打印相應的日誌 my_logger = logging.getLogger(name) return my_logger # conf/settings.py import os # test目錄 BASE_PATH = os.path.dirname(os.path.dirname(__file__)) # test/db目錄 DB_PATH = os.path.join(BASE_PATH, 'db') # 日誌配置文件 ''' logging 配置 ''' import os standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \ '[%(levelname)s][%(message)s]' #其中name爲getlogger指定的名字 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s' # 日誌目錄 LOG_PATH = os.path.join(BASE_PATH,'log') log_filename = 'Atm_Shop.log' if not os.path.isdir(LOG_PATH): os.mkdir(LOG_PATH) # log文件全路徑 logfile_path = os.path.join(LOG_PATH,log_filename) LOGGING_DIC = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': standard_format }, 'simple': { 'format': simple_format }, }, 'filters': {}, 'handlers': { #打印到終端的日誌 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 打印到屏幕 'formatter': 'simple' }, #打印到文件的日誌,收集info及以上的日誌 'default': { 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 'formatter': 'standard', 'filename': logfile_path, # 日誌文件 'maxBytes': 1024*1024*5, # 日誌大小 5M 'backupCount': 5, #日誌文件最大個數 'encoding': 'utf-8', # 日誌文件的編碼 }, }, 'loggers': { #logging.getLogger(__name__)拿到的logger配置 'aa': { 'handlers': ['default', 'console'], # 這裏把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)傳遞 }, # 把key設置爲空 '': { 'handlers': ['default', 'console'], # 這裏把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)傳遞 }, }, } # 引用 from lib import common # 獲取銀行日誌功能 bank_log = common.get_logger('bank') bank_log.info('%s提現%s元成功,手續費爲%s' % (user, money2,money3))
9、re模塊
# re:正則,全稱正則字符串 - re就是有特殊語法的字符串 # re能夠將有正則語法的字符串解析爲對應的正則對象,用來匹配目標字符串 # 學習re的目的:1.判斷目標字符串是否合法 2.在目標字符串中提取想要的信息(信息匹配規則採用正則)
import re # 從123abc123中查找1 r1 = re.findall(r'1', '123abc123') print(r1) # ['1', '1'] r2 = re.findall(r'a', '123abc123ABC', flags=re.I) # re.I 不區分大小寫匹配 print(r2) # ['a', 'A'] # 1.將 r'\d' 丟給_compile獲得能夠匹配數字的 正則對象 # 2.正則對象.findall('目標字符串') r3 = re.findall(r'\d', '123abc123') print(r3) # ['1', '2', '3', '1', '2', '3'] re_obj = re.compile(r'\d') # 將 r'\d' 丟給_compile獲得能夠匹配數字的 正則對象 r4 = re_obj.findall('123abc123') # 正則對象.findall('目標字符串') print(r4) # ['1', '2', '3', '1', '2', '3']
正則語法
單個字符語法:
import re # 1、單個字符語法 # 匹配a print(re.findall(r'a', '123abc嘿嘿')) # ['a'] # a或b print(re.findall(r'a|b', '123abc嘿嘿')) # ['a', 'b'] 不建議使用 print(re.findall(r'[ab]', '123abc嘿嘿')) # ['a', 'b'] 建議使用 # 非a非b print(re.findall(r'[^ab]', '123abc嘿嘿')) # ['1', '2', '3', 'c', '嘿', '嘿'] # 數字 print(re.findall(r'[0-9]', '12abc嘿嘿12')) # ['1', '2', '1', '2'] 建議使用 print(re.findall(r'\d', '12abc嘿嘿12')) # ['1', '2', '1', '2'] 不建議使用 # 字母 print(re.findall(r'[a-zA-Z]', '12abc[嘿嘿ABC')) # ['a', 'b', 'c', 'A', 'B', 'C'] # 字母數字_經常使用漢字:\w => 建議使用 [a-zA-Z0-9_] print(re.findall(r'\w', '12abc[_嘿嘿ABC')) # ['1', '2', 'a', 'b', 'c', '_', '嘿', '嘿', 'A', 'B', 'C'] # 漢字 [\u4e00-\u9fa5]表明漢字 print(re.findall(r'[\u4e00-\u9fa5]', '12abc[_嘿嘿ABC')) # ['嘿', '嘿'] # 空白字符:\s => 建議使用[ \f\n\r\t\v] print(re.findall(r'\s', ' \f\n\r\t\v')) # [' ', '\x0c', '\n', '\r', '\t', '\x0b'] # 非\n的任意字符: . print(re.findall(r'.', ' \f\n\r\t\v*&_.')) # [' ', '\x0c', '\r', '\t', '\x0b', '*', '&', '_', '.'] # 只想匹配.字符:\. print(re.findall(r'\.', ' \f\n\r\t\v*&_.')) # ['.'] # re.S: 讓.也能匹配\n,就能夠理解爲 . 能夠匹配全部字符 print(re.findall(r'.', ' \f\n\r\t\v*&_.', flags=re.S)) # 取對立面 \d數字 \D非數字 \w=>\W \s=>\S print(re.findall(r'\D', '12abc\f嘿嘿12')) # ['a', 'b', 'c', '\x0c', '嘿', '嘿']
重複字符語法:
print(re.findall(r'ab', 'abacbabc')) # ['ab', 'ab'] # 指定個數: 匹配abb print(re.findall(r'ab{2}', 'aababbabbb')) # ['abb', 'abb'] # 貪婪匹配: 儘量多的匹配 # a0~2個b: a | ab | abb print(re.findall(r'ab{,2}', 'aababbabbb')) # ['a', 'ab', 'abb', 'abb'] # a0~n個b: print(re.findall(r'ab{0,}', 'aababbabbb')) # ['a', 'ab', 'abb', 'abbb'] # a1~3個b: print(re.findall(r'ab{1,3}', 'aababbabbb')) # ['ab', 'abb', 'abbb'] # *: {0,} print(re.findall(r'ab*', 'aababbabbb')) # ['a', 'ab', 'abb', 'abbb'] # +: {1,} print(re.findall(r'ab+', 'aababbabbb')) # ['ab', 'abb', 'abbb'] # ?: {,1} print(re.findall(r'ab?', 'aababbabbb')) # ['a', 'ab', 'ab', 'ab'] # 非貪婪匹配 print(re.findall(r'ab{1,3}?', 'aababbabbb')) # ['ab', 'ab', 'ab'] # 重點:非貪婪匹配應用場景,通常都是結合有開頭與結尾的標識 print(re.findall(r'<.{1,}>', '<a><b>msg</b></a>')) # ['<a><b>msg</b></a>'] # 匹配標籤 print(re.findall(r'<.{1,}?>', '<a><b>msg</b></a>')) # ['<a>', '<b>', '</b>', '</a>'] # *?: {0,}? # +?: {1,}? # ??: {,1}? print(re.findall(r'<.+?>', '<a><b>msg</b></a>')) # ['<a>', '<b>', '</b>', '</a>']
分組語法:
# 引子 print(re.findall(r'(?:ab){2}', 'abbabab')) # ['abab'] # findall(): 沒有分組狀況下,顯示匹配的結果;若是有分組,顯示分組結果 # 分組:() # 取消分組:(?:) # 有名分組:(?P<名字>) # 案例: # 匹配連接 print(re.findall(r'www\..+?\.com', 'www.baidu.comabcwww.sina.com')) # ['www.baidu.com', 'www.sina.com'] # 獲取連接的域名:['baidu', 'sina'] print(re.findall(r'www\.(.+?)\.com', 'www.baidu.comabcwww.sina.com')) # ['baidu', 'sina'] # 分組編號: 從左往右數左(進行分組編號 # [('www.baidu.com', 'baidu', 'com'), ('www.sina.edu', 'sina', 'edu')] res = re.findall(r'(www\.(.+?)\.(com|edu))', 'www.baidu.comabcwww.sina.edu') print(res) print(res[0][1]) # 取消分組:(?:) 應用於,要將一些數據做爲總體看待,但由不能產生分組 # [('www.baidu.com', 'baidu'), ('www.sina.edu', 'sina')] res = re.findall(r'(www\.(.+?)\.(?:com|edu))', 'www.baidu.comabcwww.sina.edu') print(res)
其餘正則方法的使用:
# match:不是全文匹配,必須從頭開始匹配,且只匹配一次 res = re.match(r'(www\.(?P<site_name>.+?)\.(?:com|edu))', 'www.baidu.comwww.sina.edu') # 能夠經過分組號直接取出分組內容 print(res.group(1)) print(res.group(2)) # print(res.group(0), res) # 匹配的總體 # 有名分組 print(res.group('site_name')) # split(): 拆分 print('abc def xyz'.split(' ')) print(re.split(r' ', 'abc def xyz')) print(re.split(r'[,@ ]', 'abc,def@xyz opq')) # sub(): 替換 res = re.sub(r'good', 'bed', 'good good day a') print(res) # bed bed day a res = re.sub(r'good', 'bed', 'good good day a', count=1) print(res) # bed good day a res = re.sub(r'good day a', '123', 'good day a!!!') print(res) # 123!!! # 結合分組能夠完成數據的重組 res = re.sub(r'(good) (day) (a)', r'today is \3 \1 \2', 'good day a!!!') print(res) # today is a good day!!!
描述 | |
---|---|
\ | 將下一個字符標記符、或一個向後引用、或一個八進制轉義符。例如,「\n」匹配\n。「\n」匹配換行符。序列「\」匹配「\」而「(」則匹配「(」。即至關於多種編程語言中都有的「轉義字符」的概念。 |
^ | 匹配輸入字行首。若是設置了RegExp對象的Multiline屬性,^也匹配「\n」或「\r」以後的位置。 |
$ | 匹配輸入行尾。若是設置了RegExp對象的Multiline屬性,$也匹配「\n」或「\r」以前的位置。 |
* | 匹配前面的子表達式任意次。例如,zo能匹配「z」,也能匹配「zo」以及「zoo」。等價於{0,}。 |
+ | 匹配前面的子表達式一次或屢次(大於等於1次)。例如,「zo+」能匹配「zo」以及「zoo」,但不能匹配「z」。+等價於{1,}。 |
{n} | n是一個非負整數。匹配肯定的n次。例如,「o{2}」不能匹配「Bob」中的「o」,可是能匹配「food」中的兩個o。 |
{n,} | n是一個非負整數。至少匹配n次。例如,「o{2,}」不能匹配「Bob」中的「o」,但能匹配「foooood」中的全部o。「o{1,}」等價於「o+」。「o{0,}」則等價於「o*」。 |
{n,m} | m和n均爲非負整數,其中n<=m。最少匹配n次且最多匹配m次。例如,「o{1,3}」將匹配「fooooood」中的前三個o爲一組,後三個o爲一組。「o{0,1}」等價於「o?」。請注意在逗號和兩個數之間不能有空格。 |
? | 匹配前面的子表達式零次或一次。例如,「do(es)?」能夠匹配「do」或「does」。?等價於{0,1}。 |
? | 當該字符緊跟在任何一個其餘限制符(,+,?,{n},{n,},{n,m*})後面時,匹配模式是非貪婪的。非貪婪模式儘量少地匹配所搜索的字符串,而默認的貪婪模式則儘量多地匹配所搜索的字符串。例如,對於字符串「oooo」,「o+」將盡量多地匹配「o」,獲得結果[「oooo」],而「o+?」將盡量少地匹配「o」,獲得結果 ['o', 'o', 'o', 'o'] |
.點 | 匹配除「\n」和"\r"以外的任何單個字符。要匹配包括「\n」和"\r"在內的任何字符,請使用像「[\s\S]」的模式。 |
x|y | 匹配x或y。例如,「z|food」能匹配「z」或「food」(此處請謹慎)。「[zf]ood」則匹配「zood」或「food」。 |
[xyz] | 字符集合。匹配所包含的任意一個字符。例如,「[abc]」能夠匹配「plain」中的「a」。 |
[^xyz] | 負值字符集合。匹配未包含的任意字符。例如,「abc」能夠匹配「plain」中的「plin」任一字符。 |
[a-z] | 字符範圍。匹配指定範圍內的任意字符。例如,「[a-z]」能夠匹配「a」到「z」範圍內的任意小寫字母字符。注意:只有連字符在字符組內部時,而且出如今兩個字符之間時,才能表示字符的範圍; 若是出字符組的開頭,則只能表示連字符自己. |
[^a-z] | 負值字符範圍。匹配任何不在指定範圍內的任意字符。例如,「a-z」能夠匹配任何不在「a」到「z」範圍內的任意字符。 |
\b | 匹配一個單詞的邊界,也就是指單詞和空格間的位置(即正則表達式的「匹配」有兩種概念,一種是匹配字符,一種是匹配位置,這裏的\b就是匹配位置的)。例如,「er\b」能夠匹配「never」中的「er」,但不能匹配「verb」中的「er」;「\b1」能夠匹配「1_23」中的「1」,但不能匹配「21_3」中的「1_」。 |
\B | 匹配非單詞邊界。「er\B」能匹配「verb」中的「er」,但不能匹配「never」中的「er」 |
\s | 匹配任何不可見字符,包括空格、製表符、換頁符等等。等價於[ \f\n\r\t\v]。 |
\S | 匹配任何可見字符。等價於 \f\n\r\t\v。 |
\w | 匹配包括下劃線的任何單詞字符。相似但不等價於「[A-Za-z0-9_]」,這裏的"單詞"字符使用Unicode字符集。 |
\W | 匹配任何非單詞字符。等價於「A-Za-z0-9_」。 |
\d | 匹配一個數字字符。等價於[0-9]。grep 要加上-P,perl正則支持 |
\D | 匹配一個非數字字符。等價於0-9。grep要加上-P,perl正則支持 |
\n | 匹配一個換行符。等價於\x0a和\cJ。 |
\r | 匹配一個回車符。等價於\x0d和\cM。 |
\t | 匹配一個製表符。等價於\x09和\cI。 |
( ) | 將( 和 ) 之間的表達式定義爲「組」(group),而且將匹配這個表達式的字符保存到一個臨時區域(一個正則表達式中最多能夠保存9個),它們能夠用 \1 到\9 的符號來引用。 |
(?:pattern) | 非獲取匹配,匹配pattern但不獲取匹配結果,不進行存儲供之後使用。這在使用或字符「(|)」來組合一個模式的各個部分時頗有用。例如「industr(?:y|ies)」就是一個比「industry|industries」更簡略的表達式。 |
| | 將兩個匹配條件進行邏輯「或」(Or)運算。例如正則表達式(him|her) 匹配"it belongs to him"和"it belongs to her",可是不能匹配"it belongs to them."。注意:這個元字符不是全部的軟件都支持的。 |
10、shell腳本之subprocess模塊
#Popen
order = subprocess.Popen('dir',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
res = order.stdout.read().decode('gbk')
print(res)
print('==============================')
res = order.stderr.read().decode('gbk')
print(res)
# 舉例 # windows下測試列出目錄文件
# run
import subprocess
order = subprocess.run('dir',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
res = order.stdout.decode('gbk')
print(res)
print('==============================')
# stderr 輸出錯誤
res = order.stderr.decode('gbk')
print(res)
#Centos系統 >>> a = subprocess.call(['df','-lh'],shell=False) Filesystem Size Used Avail Use% Mounted on /dev/vda1 40G 9.0G 29G 25% / /dev/vdb 99G 16G 78G 18% /db tmpfs 783M 0 783M 0% /run/user/1000 >>> r1=subprocess.getstatusoutput("dir") >>> r1 (0, 'lova test.sh') >>> r2 = subprocess.Popen('ping -c2 www.baidu.com',shell=True) >>> PING www.a.shifen.com (115.239.210.27) 56(84) bytes of data. 64 bytes from 115.239.210.27 (115.239.210.27): icmp_seq=1 ttl=54 time=8.59 ms 64 bytes from 115.239.210.27 (115.239.210.27): icmp_seq=2 ttl=54 time=8.64 ms --- www.a.shifen.com ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3004ms rtt min/avg/max/mdev = 8.595/8.621/8.648/0.094 ms >>> subprocess.Popen('./test.sh',shell=True) <subprocess.Popen object at 0x7f2c51f10160> >>> Hello World! >>> res = subprocess.Popen('./test.sh',stdout = subprocess.PIPE,shell=True,stderr=subprocess.PIPE) >>> res1 = res.stdout.read() >>> res1 b'Hello World!\n' >>> print(res1) b'Hello World!\n'
12、configparser 模塊
# my.ini 配置文件讀寫 """ [server] ip = 192.168.66.88 port = 3306 [client] user = root password = root """ import configparser # 1.初始化 parser = configparser.ConfigParser() # 2.讀 parser.read('my.ini', encoding='utf-8') # section | option | value # 讀取列表 sts = parser.sections() print(sts, type(sts)) # ['server', 'client'] <class 'list'> ops = parser.options(sts[0]) print(ops) # ['ip', 'port'] value = parser.get(sts[0], ops[0]) print(value, type(value)) # 192.168.66.88 <class 'str'> # # get=>str getboolean=>bool getfloat=>float getint=>int print(parser.get('server', 'port')) # 3306 # 3.寫 parser.read('my.ini', encoding='utf-8') parser.set('server', 'port', '6666') parser.write(open('my.ini', 'w'))
十3、xml模塊
# xml文件:1.做爲傳輸文件用於數據的傳輸 2.做爲配置文件配置信息 # 1.只能由一個根標籤 # 2.全部的標籤都是自定義的 # 3.標籤名就是key,標籤的內容就是value # 4.與json不一樣的是,標籤不只能夠有key和value,還有標籤的屬性 # 注:xml的屬性一般用來表示標籤間的區分度,用於解析xml來使用
<data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor direction="E" name="Austria" /> <neighbor direction="W" name="Switzerland" /> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year>2011</year> <gdppc>88888</gdppc> <neighbor direction="N" name="Malaysia" /> </country> <country name="Panama"> <rank updated="yes">69</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor direction="W" name="Costa Rica" /> <neighbor direction="E" name="Colombia" /> </country> </data>
""" {"countrys": [ { "rank": 2, "year": 2008, "gdppc": 141100 }, {}, {} ]} { "data": { "countrys": [ {}, {}, {} ] } } """ # xml的文件解析 => 將xml轉化爲json類型的數據 # dict list => json import xml.etree.ElementTree as ET # 讀文件 tree = ET.parse("my.xml") print(tree) # xml.etree.ElementTree.ElementTree # <xml.etree.ElementTree.ElementTree object at 0x0000000001EACA58> # 根節點 root_ele = tree.getroot() print(root_ele) # Element 'data':<Element 'data' at 0x0000000001DBD4A8> # 遍歷往下 # print(root_ele[1]) for ele in root_ele: print(ele, ele.attrib) if ele.attrib['name'] == 'Singapore': for e in ele: print(e, e.tag) if e.tag == 'gdppc': print(e.text) e.text = '6666' # 只修改了內容 # 全文搜索指定名的子標籤 # ele.iter("標籤名") # 非全文查找知足條件的第一個子標籤 # ele.find("標籤名") # 非全文查找知足條件的全部子標籤 # ele.findall("標籤名") # print('==============') # cs = root_ele.iter('country') # for c in cs: # print(c) # print('==============') # print(root_ele.find('country').attrib) # {'name': 'Liechtenstein'} # print(root_ele.find('rank').attrib) # 不能跨標籤取,只能取子標籤 # print('==============') # print(root_ele.findall('country')) # 將內存的數據從新寫入文件 tree.write("my.xml")
# 讀
data = {'countrys': []}
tree = ET.parse("my.xml")
root = tree.getroot()
for ele in root:
country = {}
for e in ele:
if e.text and e.text.strip():
country[e.tag] = e.text
data['countrys'].append(country)
print(data)
十4、Excel操做
# Excel 年終報表 教學部 市場部 諮詢部 總計 Jan-19 10 15 5 30 Feb-19 11 20 5 36 Mar-19 12 25 5 42 Apr-19 13 30 5 48 May-19 14 35 5 54 Jun-19 15 40 5 60 Jul-19 16 45 5 66 Aug-19 17 50 5 72 Sep-19 18 55 5 78 Oct-19 19 60 5 84 Nov-19 20 65 5 90 Dec-19 21 70 5 96
基本操做
imimport xlrd # 讀取文件 work_book = xlrd.open_workbook("my.xlsx") # 獲取全部全部表格名稱 print(work_book.sheet_names()) # 選取一個表 sheet = work_book.sheet_by_index(0) # 表格名稱 print(sheet.name) # 行數 print(sheet.nrows) # 列數 print(sheet.ncols) # 某行所有 print(sheet.row(6)) print(sheet.row(13)) # 某列所有 print(sheet.col(4)) # 某行列區間 print(sheet.row_slice(6, start_colx=0, end_colx=4)) # 某列行區間 print(sheet.col_slice(3, start_rowx=0, end_rowx=3)) # 某行類型0:空 1:str 2:num 3:date | 值 print(sheet.row_types(1), sheet.row_values(6)) # 單元格 print(sheet.cell(6,0).value) # 取值 print(sheet.cell(6,0).ctype) # 取類型 print(sheet.cell_value(6,0)) # 直接取值 print(sheet.cell_type(6,0)) # 直接取類型 # 0:以1900年爲基準 1:以1904年爲基準 print(xlrd.xldate_as_datetime(sheet.cell(6, 0).value, 0))
import xlwt # 建立工做簿 work = xlwt.Workbook() # 建立一個表 sheet = work.add_sheet("員工信息數據") # 建立一個字體對象 # font = xlwt.Font() # font.name = "Times New Roman" # 字體名稱 # font.bold = True # 加粗 # font.italic = True # 斜體 # font.underline = True # 下劃線 # 建立一個樣式對象 # style = xlwt.XFStyle() # style.font = font keys = ['Owen', 'Zero', 'Egon', 'Liuxx', 'Yhh'] # 寫入標題 c = 0 for k in keys: # sheet.write(0, keys.index(k), k, style) # sheet.write(0, keys.index(k), k) sheet.write(keys.index(k) + 5, 2, k if k != 'Egon' else 'cool') # sheet.write(c, c, k) # c += 1 # 寫入數據 # sheet.write(1, 0, 'cool', style) # sheet.write(0, 0, 'cool') # 保存至文件 work.save("new_my.xls")