模塊定義:一系列功能的集合體html
分爲三大類:1.自定義模塊python
2.內置模塊(好比 time,os,sys)linux
3.第三方模塊git
模塊的表現形式:程序員
1.使用python編寫的py文件正則表達式
2.已被編譯爲共享庫或DLL的C或C++擴展算法
3.把一系列模塊組織到一塊兒的文件夾(ps:文件夾下有一個__init__.py文件,該文件夾稱爲包)shell
4.使用C編寫並連接到python解釋器的內置模塊編程
爲何要用模塊:json
1.能夠拿來內置、第三方的模塊,而後直接使用,這種拿來就用的方式,會極大的提高開發效率
2.將程序中共用的一些功能組織到一個文件中,而後程序各部分組件能夠重用該文件中的功能。
優勢是 減小代碼冗餘,加強程序的組織結構性與可維護性
怎麼用模塊:
一個py文件就是一個模塊,若是文件名爲modules.py,模塊名則爲modules
ps:模塊的使用必須搞清楚誰是執行文件,誰是被導入的模塊
#:coding:utf-8 #modules.py print('from the modules.py') money=1000 def read1(): print('modules模塊.read1',money) def read2(): print('modules模塊.read2') read1() def change(): global money money=0
import modules money=111111111111 print(modules.money) print(modules.read1) print(modules.read2) print(modules.change) modules.money=2222 print(money)###結果爲money=111111111111 modules.read1()#modules模塊.read1 2222 #這個更改爲功modules.money=2222 def read1():#此處定義read1 print('run.py中的read1') modules.read1()#執行結果仍爲modules模塊.read1 2222 money=20000000 modules.change()#此處執行了modules中change函數 print(money)###此處爲上述money=20000000 print(modules.money)##結果爲0 import modules as spam ##能夠as 起個別名 print(spam.money) #依舊執行成功 結果爲0
執行文件:run.py 被導入模塊是:modules.py
首次導入模塊會發生三件事:
一、建立一個模塊modules.py的名稱空間
二、執行模塊對應的文件modules.py,將產生的名字丟到模塊的名稱空間中
三、在當前執行文件的名稱空間中拿到一個名字modules,該名字就是指向模塊modules.py的名稱空間的
import modules# modules=modules.py名稱空間的內存地址
ps:
在當前執行文件中引用模塊中的名字語法爲:modules.名字,必須加上modules.做爲前綴
modules.名字至關於指名道姓地跟某一個名稱空間要名字,根本不會與當前執行文件的名字衝突
#modules.py # print('from the modules.py') __all__=['money','read1'] money=1000 def read1(): print('spam模塊.read1',money) def read2(): print('spam模塊.read2') read1() def change(): global money money=0
from spam import money,read1,read2,change # def read1(): print('run.py.read1') read1() # run.py.read1 read2() # spam模塊.read2 ------------> spam模塊.read1 1000 from spam import money as my print(my) #1000 # =========================================== from spam import * # * 會檢索被導入模塊中的__all__指定的名字,若是沒有該變量那默認導入全部 print(money) #1000 print(read1) # <function read1 at 0x0000000001EB1C80> # print(read2) #會報錯 # print(change) #會報錯
執行文件:run.py 被導入模塊: spam.py
首次導入模塊會發生三件事
一、建立一個模塊spam.py的名稱空間
二、執行模塊對應的文件spam.py,將產生的名字丟到模塊的名稱空間中
三、在當前執行文件的名稱空間中拿到一個名字money,該名字就是指向模塊spam.py的名稱空間的那個money
from spam import money,read1,read2,change
兩種導入方式的對比
相同點:函數的做用域關係在定義階段就規定死了,與調用位置無關
from import
優勢:能夠不用加前綴而直接引用名字,更簡潔
缺點:容易與當前執行文件中的名字衝突
import
優勢:指名道姓跟某一個名稱空間要名字,確定不會與當前名稱空間中的名字衝突
缺點:必須加上前綴
# print('正在導入m1') # # x='m1.py' # # from m2 import y # print('正在導入m1') def f1(): from m2 import y,f2 print(y) f2() x='m1.py'
# print('正在導入m2') # # y='m2' # # from m1.py import x print('正在導入m2') def f2(): from m1 import x print(x) y='m2.py'
### run.py # 一、建立m1.py的名稱空間 # 二、執行m1.py的代碼,將產生的名字丟到m1.py的名稱空間中 # 三、在當前執行文件的名稱空間中拿到一個名字m1 import m1 m1.f1()
模塊搜索路徑優先級:
內存 --------> 內置的模塊 --------> sys.path(環境變量)
#模塊的查找順序 1、在第一次導入某個模塊時(好比spam),會先檢查該模塊是否已經被加載到內存中(當前執行文件的名稱空間對應的內存),若是有則直接引用 ps:python解釋器在啓動時會自動加載一些模塊到內存中,可使用sys.modules查看 2、若是沒有,解釋器則會查找同名的內建模塊 3、若是尚未找到就從sys.path給出的目錄列表中依次尋找spam.py文件。 #sys.path的初始化的值來自於: The directory containing the input script (or the current directory when no file is specified). PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH). The installation-dependent default. #須要特別注意的是:咱們自定義的模塊名不該該與系統內置模塊重名。雖然每次都說,可是仍然會有人不停的犯錯。 #在初始化後,python程序能夠修改sys.path,路徑放到前面的優先於標準庫被加載。 1 >>> import sys 2 >>> sys.path.append('/a/b/c/d') 3 >>> sys.path.insert(0,'/x/y/z') #排在前的目錄,優先被搜索 注意:搜索時按照sys.path中從左到右的順序查找,位於前的優先被查找,sys.path中還可能包含.zip歸檔文件和.egg文件,python會把.zip歸檔文件當成一個目錄去處理, #首先製做歸檔文件:zip module.zip foo.py bar.py import sys sys.path.append('module.zip') import foo,bar #也可使用zip中目錄結構的具體位置 sys.path.append('module.zip/lib/python') #windows下的路徑不加r開頭,會語法錯誤 sys.path.insert(0,r'C:\Users\Administrator\PycharmProjects\a') #至於.egg文件是由setuptools建立的包,這是按照第三方python庫和擴展時使用的一種常見格式,.egg文件實際上只是添加了額外元數據(如版本號,依賴項等)的.zip文件。 #須要強調的一點是:只能從.zip文件中導入.py,.pyc等文件。使用C編寫的共享庫和擴展塊沒法直接從.zip文件中加載(此時setuptools等打包系統有時能提供一種規避方法),且從.zip中加載文件不會建立.pyc或者.pyo文件,所以必定要事先建立他們,來避免加載模塊是性能降低。
一個python文件有兩種用途:(模塊與腳本)
一、能夠執行運行:__name__ == '__main__'
二、能夠被當作模塊導入:__name__ == '模塊名'
if __name__ == '__main__':
官網解釋
Packages are a way of structuring Python’s module namespace by using 「dotted module names」
包是一種經過使用‘.模塊名’來組織python模塊名稱空間的方式。
具體的:包就是一個包含有__init__.py文件的文件夾,因此其實咱們建立包的目的就是爲了用文件夾將文件/模塊組織起來
須要強調的是:
1. 在python3中,即便包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下必定要有該文件,不然import 包報錯
2. 建立包的目的不是爲了運行,而是被導入使用,記住,包只是模塊的一種形式而已,包的本質就是一種模塊
包的本質就是一個文件夾, 那麼文件夾惟一的功能就是將文件組織起來 隨着功能越寫越多 ,咱們沒法將因此功能都放到一個文件中, 因而咱們使用模塊去組織功能, 而隨着模塊愈來愈多, 咱們就須要用文件夾將模塊文件組織起來,以此來提升程序的結構性和可維護性。
ps:注意事項
#1.關於包相關的導入語句也分爲import和from ... import ...兩種,可是不管哪一種,不管在什麼位置,在導入時都必須遵循一個原則:凡是在導入時帶點的,點的左邊都必須是一個包,不然非法。能夠帶有一連串的點,如item.subitem.subsubitem,但都必須遵循這個原則。但對於導入後,在使用時就沒有這種限制了,點的左邊能夠是包,模塊,函數,類(它們均可以用點的方式調用本身的屬性)。 #二、import導入文件時,產生名稱空間中的名字來源於文件,import 包,產生的名稱空間的名字一樣來源於文件,即包下的__init__.py,導入包本質就是在導入該文件 #三、包A和包B下有同名模塊也不會衝突,如A.a與B.a來自倆個命名空間
|---示例 | ||---dir1 #文件夾 | | |-----dir2 #文件夾 | | |---p1 #包文件夾 | | |||-------p2 #包文件夾 | | ||| ||----- __init__.py | | ||| |------m3.py | | ||| | | |||--- __init__.py | | ||----m1.py | | |-----m2.py | | | |------run.py #執行文件
# run.py from dir1.dir2 import p1 p1.f1() p1.f2() p1.f3() #====================================== #dir1文件夾 (dir2文件夾) # #dir2文件夾(p1包文件夾) #====================================== #p1下的文件內容 #__init.py from .m1 import f1 from .m2 import f2 from .p2.m3 import f3 #------------------------------------------ #m1.py def f1(): print('m1.f1') #------------------------------------------- #m2.py def f2(): print('m2.f2') #------------------------------------------- #p1包文件夾(p2包文件夾) #======================================= #p2下的文件內容 #__init__.py #空 #-------------------------------------------- #m3.py def f3(): print('m3.f3')
#import p1 #1 建立p1的名稱空間 #2 執行p1下的__init__.py文件的代碼,將執行過程當中產生的名字都丟到名稱空間中 #3 在當前執行文件中拿到一個名字p1,p1指向__init__.py的名稱空間
#包內模塊的:絕對導入與相對導入 # 絕對導入:每次導入都是以最頂級包爲起始開始查找的 # 相對導入:相對於當前所在的文件,.表明當前所在的文件,..表明上一級,... # 強調: # 相對導入只能在被導入的模塊中使用 # 在執行文件裏不能用.或者..的導入方式 #注意: # 但凡在導入時帶點的,點的左邊必須是一個包
一、bin 文件夾 :通常放程序啓動文件(start.py)
二、conf 文件夾:一些配置信息(例如路徑等)
三、core 文件夾:程序的核心文件 與用戶掛鉤的
四、db 文件夾 :數據文件所在地
五、lib 文件夾 :公共模塊文件(例如認證文件)
六、log 文件夾 :日誌文件所在地
七、Readme 文件 :程序的幫助文檔
CRITICAL = 50 #FATAL = CRITICAL ERROR = 40 WARNING = 30 #WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0 #不設置
import logging logging.debug('調試debug') logging.info('消息info') logging.warning('警告warn') logging.error('錯誤error') logging.critical('嚴重critical') ''' WARNING:root:警告warn ERROR:root:錯誤error CRITICAL:root:嚴重critical '''
針對全部logger有效,控制打印到文件
可在logging.basicConfig()函數中經過具體參數來更改logging模塊默認行爲,可用參數有
filename:用指定的文件名建立FiledHandler,這樣日誌會被存儲在指定的文件中。 filemode:文件打開方式,在指定了filename時使用這個參數,默認值爲「a」還可指定爲「w」。 format:指定handler使用的日誌顯示格式。 datefmt:指定日期時間格式。 level:設置rootlogger 的日誌級別 stream:用指定的stream建立StreamHandler。能夠指定輸出到sys.stderr,sys.stdout或者文件,默認爲sys.stderr。若同時列出了filename和stream兩個參數,則stream參數會被忽略。 #格式 %(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:用戶輸出的消息
#========使用 import logging logging.basicConfig(filename='access.log', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level=10) logging.debug('調試debug') logging.info('消息info') logging.warning('警告warn') logging.error('錯誤error') logging.critical('嚴重critical') #========結果 access.log內容: 2017-07-28 20:32:17 PM - root - DEBUG -test: 調試debug 2017-07-28 20:32:17 PM - root - INFO -test: 消息info 2017-07-28 20:32:17 PM - root - WARNING -test: 警告warn 2017-07-28 20:32:17 PM - root - ERROR -test: 錯誤error 2017-07-28 20:32:17 PM - root - CRITICAL -test: 嚴重critical part2: 能夠爲logging模塊指定模塊級的配置,即全部logger的配置
Formatter ,Handler,Logger,Filte
#logger:產生日誌的對象 #Filter:過濾日誌的對象 #Handler:接收日誌而後控制打印到不一樣的地方,FileHandler用來打印到文件中,StreamHandler用來打印到終端 #Formatter對象:能夠定製不一樣的日誌格式對象,而後綁定給不一樣的Handler對象使用,以此來控制不一樣的Handler的日誌格式
''' critical=50 error =40 warning =30 info = 20 debug =10 ''' import logging #一、logger對象:負責產生日誌,而後交給Filter過濾,而後交給不一樣的Handler輸出 logger=logging.getLogger(__file__)#日誌名 #二、Filter對象:不經常使用,略 #三、Handler對象:接收logger傳來的日誌,而後控制輸出 h1=logging.FileHandler('t1.log') #打印到文件 h2=logging.FileHandler('t2.log') #打印到文件 h3=logging.StreamHandler() #打印到終端 #四、Formatter對象:日誌格式 formmater1=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p',) formmater2=logging.Formatter('%(asctime)s : %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p',) formmater3=logging.Formatter('%(name)s %(message)s',) #五、爲Handler對象綁定格式 h1.setFormatter(formmater1) h2.setFormatter(formmater2) h3.setFormatter(formmater3) #六、將Handler添加給logger並設置日誌級別 logger.addHandler(h1) logger.addHandler(h2) logger.addHandler(h3) logger.setLevel(10) #七、測試 logger.debug('debug') logger.info('info') logger.warning('warning') logger.error('error') logger.critical('critical')
一、配圖
logger1=logging.getLogger('xx日誌')
二、filter過濾(基本用不到)
handler對象須要與logger對象綁定用來接收logger對象傳過來的日誌,控制打印到不一樣的地方(文件、終端)
fh1=logging.FileHandler(filename='a1.log',encoding='utf-8') fh2=logging.FileHandler(filename='a2.log',encoding='utf-8') sh=logging.StreamHandler()# 往終端打印的
formmater對象須要與handler對象綁定,用於控制handler對象的日誌格式
formmater1=logging.Formatter( fmt='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p' ) #兩種不一樣的日誌格式 formmater2=logging.Formatter( fmt='%(asctime)s - %(levelname)s : %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p' )
ps1:設置日誌級別(統一設置):logger與handler兩層關卡都放行,日誌最終才放行
logger1.setLevel(10) #logger對象設置 fh1.setLevel(10) #文件1的handler設置級別 fh2.setLevel(20) #文件2的handler設置級別 sh.setLevel(30) #打印到終端的handler設置級別
ps2:創建logger對象與handler對象的綁定關係
logger1.addHandler(fh1)
logger1.addHandler(fh2)
logger1.addHandler(sh)
ps3:創建handler對象與formmater對象的綁定關係
fh1.setFormatter(formmater1)
fh2.setFormatter(formmater1)
sh.setFormatter(formmater2)
最終:使用logger1對象產生日誌,打印到不一樣的位置
logger1.debug('蘑菇買彩票中獎30元') logger1.warning('蘑菇花了1000元買彩票')
logger與handler兩層關卡都放行,日誌最終才放行
注意:logger是第一層關卡 ,而後纔到handler
import logging form=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p',) ch=logging.StreamHandler() ch.setFormatter(form) # ch.setLevel(10) ch.setLevel(20) l1=logging.getLogger('root') # l1.setLevel(20) l1.setLevel(10) l1.addHandler(ch) l1.debug('l1 debug')
若是每次使用模塊都得按照上述的步驟,那就太繁瑣了。
因此logging模塊有一個從字典中加載配置的方法
""" logging配置 """ import os import logging.config # 定義三種日誌輸出格式 開始 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_dir = os.path.dirname(os.path.abspath(__file__)) # log文件的目錄 logfile_name = 'all2.log' # log文件名 # 若是不存在定義的日誌目錄就建立一個 if not os.path.isdir(logfile_dir): os.mkdir(logfile_dir) # log文件的全路徑 logfile_path = os.path.join(logfile_dir, logfile_name) # log配置字典 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', # 日誌文件的編碼,不再用擔憂中文log亂碼了 }, }, 'loggers': { #logging.getLogger(__name__)拿到的logger配置 '': { 'handlers': ['default', 'console'], # 這裏把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)傳遞 }, }, } def load_my_logging_cfg(): logging.config.dictConfig(LOGGING_DIC) # 導入上面定義的logging配置 logger = logging.getLogger(__name__) # 生成一個log實例 logger.info('It works!') # 記錄該文件的運行狀態 if __name__ == '__main__': load_my_logging_cfg() logging配置文件
""" MyLogging Test """ import time import logging import my_logging # 導入自定義的logging配置 logger = logging.getLogger(__name__) # 生成logger實例 def demo(): logger.debug("start range... time:{}".format(time.time())) logger.info("中文測試開始。。。") for i in range(10): logger.debug("i:{}".format(i)) time.sleep(0.2) else: logger.debug("over range... time:{}".format(time.time())) logger.info("中文測試結束。。。") if __name__ == "__main__": my_logging.load_my_logging_cfg() # 在你程序文件的入口加載自定義logging配置 demo()
#一、有了上述方式咱們的好處是:全部與logging模塊有關的配置都寫到字典中就能夠了,更加清晰,方便管理 #二、咱們須要解決的問題是: 1、從字典加載配置:logging.config.dictConfig(settings.LOGGING_DIC) 2、拿到logger對象來產生日誌 logger對象都是配置到字典的loggers 鍵對應的子字典中的 按照咱們對logging模塊的理解,要想獲取某個東西都是經過名字,也就是key來獲取的 因而咱們要獲取不一樣的logger對象就是 logger=logging.getLogger('loggers子字典的key名') 但問題是:若是咱們想要不一樣logger名的logger對象都共用一段配置,那麼確定不能在loggers子字典中定義n個key 'loggers': { 'l1': { 'handlers': ['default', 'console'], # 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)傳遞 }, 'l2: { 'handlers': ['default', 'console' ], 'level': 'DEBUG', 'propagate': False, # 向上(更高level的logger)傳遞 }, 'l3': { 'handlers': ['default', 'console'], # 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)傳遞 }, } #咱們的解決方式是,定義一個空的key 'loggers': { '': { 'handlers': ['default', 'console'], 'level': 'DEBUG', 'propagate': True, }, } 這樣咱們再取logger對象時 logging.getLogger(__name__),不一樣的文件__name__不一樣,這保證了打印日誌時標識信息不一樣,可是拿着該名字去loggers裏找key名時卻發現找不到,因而默認使用key=''的配置
|----示例 | |---bin | | |----start.py #啓動文件 | | | |---conf | | |----settings.py #配置文件(logging配置) | | | |---core | | |---- src.py #業務核心邏輯 | | | |---lib | | |---- common.py #公共庫 | | | |--- log #日誌
import os BASE_DIR=os.path.dirname(os.path.dirname(__file__)) 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文件的全路徑 fh1_logfile_path = r'%s\%s\%s' %(BASE_DIR,'log','b1.log') fh2_logfile_path = r'%s\%s\%s' %(BASE_DIR,'log','b2.log') # log配置字典 LOGGING_DIC = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'standard': { 'format': standard_format }, 'simple': { 'format': simple_format }, }, 'filters': {}, 'handlers': { #打印到終端的日誌,使用的格式爲 simple_format 'ch': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', # 打印到屏幕 'formatter': 'simple' }, #打印到文件b1.log的日誌,使用的格式爲 standard_format 'fh1': { 'level': 'DEBUG', 'class': 'logging.FileHandler', # 保存到文件 'formatter': 'standard', 'filename': fh1_logfile_path, # 日誌文件 'encoding': 'utf-8', # 日誌文件的編碼,不再用擔憂中文log亂碼了 }, #打印到文件b2.log的日誌,使用的格式爲 standard_format 'fh2': { 'level': 'DEBUG', 'class': 'logging.FileHandler', # 保存到文件 'formatter': 'standard', 'filename': fh2_logfile_path, # 日誌文件 'encoding': 'utf-8', # 日誌文件的編碼,不再用擔憂中文log亂碼了 }, }, 'loggers': { '': { 'handlers': ['ch', 'fh1','fh2'], # 這裏把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕 'level': 'DEBUG', 'propagate': False, }, }, }
from conf import settings import logging.config def get_logger(name): logging.config.dictConfig(settings.LOGGING_DIC) logger1=logging.getLogger(name) return logger1
from lib import common logger1=common.get_logger("交易日誌") def shopping(): print('購物') def pay(): print('支付') logger1.info('蘑菇 支付了1元') def transfer(): print('轉帳') logger1.info('蘑菇給小火柴支付了200元') def withdraw(): print('提現') logger1.info('蘑菇提現200元') func_dic={ '1': shopping, '2': pay, '3': transfer, '4': withdraw } def run(): while True: print(""" 0 退出 1 購物 2 支付 3 轉帳 4 提現 """) choice=input('請輸入您的操做: ').strip() if choice == '0':break if choice not in func_dic: print("輸入的指令不存在,請從新輸入") continue func_dic[choice]()
import sys import os BASE_DIR=os.path.dirname(os.path.dirname(__file__)) sys.path.append(BASE_DIR) from core import src if __name__ == '__main__': src.run()
正則就是 用一些具體特殊含義的符號組合到一塊兒(稱爲正則表達式)來描述字符或字符串的方法。或者說正則就是用來描述一類事物的規則。python中,它內嵌在python中,並經過re模塊實現。
正則表達式被編譯成一系列的字節碼,而後由C編寫的匹配引擎執行。
生活中到處是正則:
好比咱們描述:4條腿
就會想到四條腿的動物或者桌子,椅子
再描述:四條腿,活的
就只有四條腿的動物這類
#==========================re模塊 正則表達式============================= import re #一、 \w匹配數字字母下劃線 print(re.findall('\w','hello 123 - _ *()')) #['h', 'e', 'l', 'l', 'o', '1', '2', '3', '_'] print(re.findall('mogu','hello mogu, mogu say hello'))#前面mogu表明徹底匹配 #['mogu', 'mogu'] #二、 \W 上方的取反 print(re.findall('\W','hello 123 - _ *()')) #[' ', ' ', '-', ' ', ' ', '*', '(', ')'] #三、 \s 匹配任意空白字符 print(re.findall('\s','666 \t jiayou')) #[' ', '\t', ' '] # \S 上方取反 #四、 \d 匹配任意數字 \D 取反匹配任意數字 print(re.findall('\d','666 \t jia\nyou')) #['6', '6', '6'] #五、 \n 只匹配換行符, \t 只匹配製表符 print(re.findall('\n','666 \t jia\nyou')) print(re.findall('\t','666 \t jia\nyou')) #['\n'] #['\t'] #六、 ^ 匹配字符串的開頭 $ 匹配字符串的結尾 print(re.findall('^mogu','hello mogu, mogu say hello')) print(re.findall('mogu$','hello mogu, mogu say hello mogu')) # ^結果爲空 只匹配開頭 # $ ['mogu'] 只匹配匹配末尾 #七、 . :點 表明匹配除了換行符之外的任意單個字符 print(re.findall('a.c','a-c a*c a2c a\nc aacacacacac a c a\tc',re.DOTALL)) # ['a-c', 'a*c', 'a2c', 'aac', 'a c', 'a\tc'] # re.DOTALL 可讓換行符也匹配出來 #八、 [] : 表明匹配指定範圍的任意字符 print(re.findall('\d[-+*/]\d','1+2 3!3 qweasd 2+3 1/2 2-3 axcz hello')) #['1+2', '2+3', '1/2', '2-3'] print(re.findall('a[0-9]c','a1c aAc a2c acc axc a23c a*c a9c')) #['a1c', 'a2c', 'a9c'] print(re.findall('a[0-9][0-9]c','a1c aAc a2c acc axc a23c a*c a9c')) #['a23c'] print(re.findall('a[a-z]c','a1c aAc a2c acc axc a23c a*c a9c')) #['acc', 'axc'] print(re.findall('a[A-Z]c','a1c aAc a2c acc axc a23c a*c a9c')) #['aAc'] #九、重複匹配 #9.1 ? : 表明左邊那一個字符出現0次或者1次 能夠用{0,1} print(re.findall('ab?','b ab abb bbabbabbabba')) #['ab', 'ab', 'ab', 'ab', 'ab', 'a'] #9.2 * :表明左邊那一個字符出現0次或者無窮次,若是沒有能夠湊合,但若是>1個,有多少就必須拿多少 # 能夠用{0,} print(re.findall('ab*','b ab abb bbabbababba')) #['ab', 'abb', 'abb', 'ab', 'abb', 'a'] #9.3 + :表明左邊那一個字符出現1次或者無窮次,至少要有一個,但若是有>1個,有多少就必須拿多少 # 能夠用{1,} print(re.findall('ab+','b ab abb bbabbabbabba')) #['ab', 'abb', 'abb', 'abb', 'abb'] #9.4 {n,m}:表明左邊那一個字符出現n次到m次,至少要有n個,但若是有>n個,就拿<=m個 print(re.findall('ab{2,5}','b ab abb bbabbabbabba abbbbbbbb')) #['abb', 'abb', 'abb', 'abb', 'abbbbb'] #9.5 .* : 匹配0個或無窮個任意字符,默認是貪婪匹配 print(re.findall('a.*c','a123c hello ab123 c321 mogu c')) # ['a123c hello ab123 c321 mogu c'] 找離a最遠的c #9.6 .*? : 匹配0個或無窮個任意字符,非貪婪匹配 print(re.findall('a.*?c','a123c hello ab123 c321 mogu c')) #['a123c', 'ab123 c'] 找離a最近的c #示例: 正則使用非貪婪匹配 ()括號的意思是 只取分組內的內容 print(re.findall('href="(.*?)"','' '<div class="div1"><a href="https://www.baidu.com">點我啊</a>' '</div><div class="div1"><a href="https://www.python.org">點我啊</a></div>'))
#[] print(re.findall('a[1*-]b','a1b a*b a-b')) #[]內的都爲普通字符了,且若是-沒有被轉意的話,應該放到[]的開頭或結尾 print(re.findall('a[^1*-]b','a1b a*b a-b a=b')) #[]內的^表明的意思是取反,因此結果爲['a=b'] print(re.findall('a[0-9]b','a1b a*b a-b a=b')) #[]內的^表明的意思是取反,因此結果爲['a=b'] print(re.findall('a[a-z]b','a1b a*b a-b a=b aeb')) #[]內的^表明的意思是取反,因此結果爲['a=b'] print(re.findall('a[a-zA-Z]b','a1b a*b a-b a=b aeb aEb')) #[]內的^表明的意思是取反,因此結果爲['a=b'] #\# print(re.findall('a\\c','a\c')) #對於正則來講a\\c確實能夠匹配到a\c,可是在python解釋器讀取a\\c時,會發生轉義,而後交給re去執行,因此拋出異常 print(re.findall(r'a\\c','a\c')) #r表明告訴解釋器使用rawstring,即原生字符串,把咱們正則內的全部符號都當普通字符處理,不要轉義 print(re.findall('a\\\\c','a\c')) #同上面的意思同樣,和上面的結果同樣都是['a\\c'] #():分組 print(re.findall('ab+','ababab123')) #['ab', 'ab', 'ab'] print(re.findall('(ab)+123','ababab123')) #['ab'],匹配到末尾的ab123中的ab print(re.findall('(?:ab)+123','ababab123')) #findall的結果不是匹配的所有內容,而是組內的內容,?:可讓結果爲匹配的所有內容 print(re.findall('href="(.*?)"','<a href="http://www.baidu.com">點擊</a>'))#['http://www.baidu.com'] print(re.findall('href="(?:.*?)"','<a href="http://www.baidu.com">點擊</a>'))#['href="http://www.baidu.com"'] #| print(re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company'))
import re #1 findall print(re.findall('e','mogu like read') ) #['e', 'e'],findall返回全部知足匹配條件的結果,放在列表裏 #2 search print(re.search('e','mogu like read').group())# e,只到找到第一個匹配而後返回一個包含匹配信息的對象,該對象能夠經過調用group()方法獲得匹配的字符串,若是字符串沒有匹配,則返回None。 #3 match print(re.match('e','mogu like read')) #None,同search,不過在字符串開始處進行匹配,徹底能夠用search+^代替match #4 split print(re.split('[ ]','mogu like read')) #['mogu', 'like', 'read'],先按'空格'分割獲得'mogu' 'like' 'read' #5 print('===>',re.sub('m','M','mogu like read movie')) #===> Mogu like read Movie,不指定n,默認替換全部 print('===>',re.sub('m','M','mogu like read movie',1)) #===> Mogu like read movie print('===>',re.sub('m','M','mogu like read movie',2)) #===> Mogu like read Movie print('===>',re.sub('^(\w+)(.*?\s)(\w+)(.*?\s)(\w+)(.*?)$',r'\5\2\3\4\1','mogu like read movie')) #===> read like mogu print('===>',re.subn('m','M','mogu like read movie')) #===> ('Mogu like read Movie', 2),結果帶有總共替換的個數 #6 obj=re.compile('\d{2}') #封裝一種正則匹配模式 print(obj.search('abc123eeee').group()) #12 print(obj.findall('abc123eeee')) #['12'],重用了obj #======================================= print(re.findall(r'-?\d+\.?\d*',"1-12*(60+(-40.35/5)-(-4*3))")) #找出全部數字['1', '-12', '60', '-40.35', '5', '-4', '3'] #使用|,先匹配的先生效,|左邊是匹配小數,而findall最終結果是查看分組,全部即便匹配成功小數也不會存入結果 #而不是小數時,就去匹配(-?\d+),匹配到的天然就是,非小數的數,在此處即整數 print(re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")) #找出全部整數['1', '-2', '60', '', '5', '-4', '3']
#爲什麼一樣的表達式search與findall卻有不一樣結果: print(re.search('\(([\+\-\*\/]*\d+\.?\d*)+\)',"1-12*(60+(-40.35/5)-(-4*3))").group()) #(-40.35/5) print(re.findall('\(([\+\-\*\/]*\d+\.?\d*)+\)',"1-12*(60+(-40.35/5)-(-4*3))")) #['/5', '*3'] #看這個例子:(\d)+至關於(\d)(\d)(\d)(\d)...,是一系列分組 print(re.search('(\d)+','123').group()) #group的做用是將全部組拼接到一塊兒顯示出來 print(re.findall('(\d)+','123')) #findall結果是組內的結果,且是最後一個組的結果
儘可能精簡,詳細的以下
儘可能使用泛匹配模式.*
儘可能使用非貪婪模式:.*?
使用括號獲得匹配目標:用group(n)去取得結果
有換行符就用re.S:修改模式
在線測試 :正則測試
在Python中,一般有這幾種方式來表示時間:
import time
#--------------------------當前時間爲準,三種形式的時間 print(time.time()) # 時間戳:1536155758.0554852 print(time.strftime("%Y-%m-%d %X")) #格式化的時間字符串:'2018-09-05 21:55:58' print(time.localtime()) #本地時區的struct_time print(time.gmtime()) #UTC時區的struct_time
%a Locale’s abbreviated weekday name. %A Locale’s full weekday name. %b Locale’s abbreviated month name. %B Locale’s full month name. %c Locale’s appropriate date and time representation. %d Day of the month as a decimal number [01,31]. %H Hour (24-hour clock) as a decimal number [00,23]. %I Hour (12-hour clock) as a decimal number [01,12]. %j Day of the year as a decimal number [001,366]. %m Month as a decimal number [01,12]. %M Minute as a decimal number [00,59]. %p Locale’s equivalent of either AM or PM. (1) %S Second as a decimal number [00,61]. (2) %U Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0. (3) %w Weekday as a decimal number [0(Sunday),6]. %W Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. (3) %x Locale’s appropriate date representation. %X Locale’s appropriate time representation. %y Year without century as a decimal number [00,99]. %Y Year with century as a decimal number. %z Time zone offset indicating a positive or negative time difference from UTC/GMT of the form +HHMM or -HHMM, where H represents decimal hour digits and M represents decimal minute digits [-23:59, +23:59]. %Z Time zone name (no characters if no time zone exists). %% A literal '%' character.
其中計算機認識的時間只能是'時間戳'格式,而程序員可處理的或者說人類能看懂的時間有: '格式化的時間字符串','結構化的時間'
import time #--------------------------按圖1轉換時間 # localtime([secs]) # 將一個時間戳轉換爲當前時區的struct_time。secs參數未提供,則以當前時間爲準。 time.localtime() time.localtime(1473525444.037215) # gmtime([secs]) 和localtime()方法相似,gmtime()方法是將一個時間戳轉換爲UTC時區(0時區)的struct_time。 # mktime(t) : 將一個struct_time轉化爲時間戳。 print(time.mktime(time.localtime()))#1536156163.0 # strftime(format[, t]) : 把一個表明時間的元組或者struct_time(如由time.localtime()和 # time.gmtime()返回)轉化爲格式化的時間字符串。若是t未指定,將傳入time.localtime()。若是元組中任何一個 # 元素越界,ValueError的錯誤將會被拋出。 print(time.strftime("%Y-%m-%d %X", time.localtime()))#2018-09-05 22:02:43 # time.strptime(string[, format]) # 把一個格式化時間字符串轉化爲struct_time。實際上它和strftime()是逆操做。 print(time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X')) # time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6, tm_wday=3, tm_yday=125, tm_isdst=-1) #在這個函數中,format默認爲:"%a %b %d %H:%M:%S %Y"。
import time #--------------------------按圖2轉換時間 # asctime([t]) : 把一個表示時間的元組或者struct_time表示爲這種形式:'Sun Jun 20 23:21:05 1993'。 # 若是沒有參數,將會將time.localtime()做爲參數傳入。 print(time.asctime())#Wed Sep 5 22:06:41 2018 # ctime([secs]) : 把一個時間戳(按秒計算的浮點數)轉化爲time.asctime()的形式。若是參數未給或者爲 # None的時候,將會默認time.time()爲參數。它的做用至關於time.asctime(time.localtime(secs))。 print(time.ctime()) # Wed Sep 5 22:06:41 2018 print(time.ctime(time.time())) # Wed Sep 5 22:06:41 2018
#時間加減 import datetime,time print(datetime.datetime.now()) #返回 2018-09-05 22:08:48.246537 print(datetime.date.fromtimestamp(time.time()) ) # 時間戳直接轉成日期格式 2018-09-05 # print(datetime.datetime.now() + datetime.timedelta(3)) #當前時間+3天 print(datetime.datetime.now() + datetime.timedelta(-3)) #當前時間-3天 print(datetime.datetime.now() + datetime.timedelta(hours=3)) #當前時間+3小時 print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #當前時間+30分 # c_time = datetime.datetime.now() print(c_time.replace(minute=3,hour=2)) #時間替換
咱們把對象(變量)從內存中變成可存儲或傳輸的過程稱之爲序列化,在Python中叫pickling,在其餘語言中也被稱之爲serialization,marshalling,flattening等等,都是一個意思。
需知一個軟件/程序的執行就在處理一系列狀態的變化,在編程語言中,'狀態'會以各類各樣有結構的數據類型(也可簡單的理解爲變量)的形式被保存在內存中。
內存是沒法永久保存數據的,當程序運行了一段時間,咱們斷電或者重啓程序,內存中關於這個程序的以前一段時間的數據(有結構)都被清空了。
在斷電或重啓程序以前將程序當前內存中全部的數據都保存下來(保存到文件中),以便於下次程序執行可以從文件中載入以前的數據,而後繼續執行,這就是序列化。
具體的來講,你玩使命召喚闖到了第13關,你保存遊戲狀態,關機走人,下次再玩,還能從上次的位置開始繼續闖關。或如,虛擬機狀態的掛起等。
序列化以後,不只能夠把序列化後的內容寫入磁盤,還能夠經過網絡傳輸到別的機器上,若是收發的雙方約定好實用一種序列化的格式,那麼便打破了平臺/語言差別化帶來的限制,實現了跨平臺數據交互。
反過來,把變量內容從序列化的對象從新讀到內存裏稱之爲反序列化,即unpickling。
若是咱們要在不一樣的編程語言之間傳遞對象,就必須把對象序列化爲標準格式,好比XML,但更好的方法是序列化爲JSON,由於JSON表示出來就是一個字符串,能夠被全部語言讀取,也能夠方便地存儲到磁盤或者經過網絡傳輸。JSON不只是標準格式,而且比XML更快,並且能夠直接在Web頁面中讀取,很是方便。
JSON表示的對象就是標準的JavaScript語言的對象,JSON和Python內置的數據類型對應以下:
# =======================序列化與反序列化方法一 json.dumps======================= import json user_dict={} name=input('名字:').strip() age=input('年齡:').strip() user_dict['name']=name user_dict['age']=age user_dict['is_beautiful']=True print(user_dict) #{'name': 'mogu', 'age': '19', 'is_beautiful': True} m=json.dumps(user_dict) # 這一步。。。 with open('%s.json'%name,'w') as f: f.write(m) #==============================反序列化========================================== name=input('名字:').strip() with open('%s.json'%name,'r') as f: msg=json.loads(f.read()) print(msg)
# =======================序列化與反序列化方法二 json.dump======================= import json user_dict={} name=input('名字:').strip() age=input('年齡:').strip() user_dict['name']=name user_dict['age']=age user_dict['is_beautiful']=True print(user_dict) #{'name': 'mogu', 'age': '19', 'is_beautiful': True} # 這裏無需再dumps with open('%s.json'%name,'w') as f: json.dump(user_dict,f) #傳對象與文件 # ==============================反序列化之 json.load========================================== name=input('名字:').strip() with open('%s.json'%name,'r') as f: msg=json.load(f) #load 默認作了f.read() print(msg)
import json #dct="{'1':111}"#json 不認單引號 #dct=str({"1":111})#報錯,由於生成的數據仍是單引號:{'one': 1} dct='{"1":"111"}' print(json.loads(dct)) #conclusion: # 不管數據是怎樣建立的,只要知足json格式,就能夠json.loads出來,不必定非要dumps的數據才能loads
# =======================序列化與反序列化 pickle.dumps======================= import pickle user_dict={} name=input('名字:').strip() age=input('年齡:').strip() user_dict['name']=name user_dict['age']=age user_dict['is_beautiful']=True print(user_dict) #{'name': 'mogu', 'age': '19', 'is_beautiful': True} m=pickle.dumps(user_dict) #序列化獲得bytes with open('%s.pickle'%name,'wb')as f: #注意w是寫入str,wb是寫入bytes,m是'bytes' f.write(m) # ==============================反序列化之 pickle.loads========================================== name=input('名字:').strip() with open('%s.pickle'%name,'rb') as f: msg=pickle.loads(f.read()) print(msg)
方法其實與 json 如出一轍
Pickle的問題和全部其餘編程語言特有的序列化問題同樣,就是它只能用於Python,而且可能不一樣版本的Python彼此都不兼容,所以,只能用Pickle保存那些不重要的數據,不能成功地反序列化也不要緊。
hash是一種算法(3.x裏代替了md5模塊和sha模塊,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法),該算法接受傳入的內容,通過運算獲得一串hash值。
2.1 只要傳入的內容同樣,獲得的hash值必然同樣 -----> 要用明文傳輸密碼文件完整性校驗
2.2 不能由hash值返解成內容 -------> 把密碼作成hash值,不該該在網絡傳輸明文密碼
2.3 只要使用的hash算法不變,不管校驗的內容有多大,獲得的hash值長度是固定的
hash算法就像一座工廠,工廠接收你送來的原材料(能夠用m.update()爲工廠運送原材料),通過加工返回的產品就是hash值
import hashlib m=hashlib.md5()# m=hashlib.sha256() m.update('hello'.encode('utf8')) print(m.hexdigest()) #5d41402abc4b2a76b9719d911017c592 m.update('world'.encode('utf8')) print(m.hexdigest()) #fc5e038d38a57032085441e7fe7010b0 m2=hashlib.md5() m2.update('helloworld'.encode('utf8')) print(m2.hexdigest()) #fc5e038d38a57032085441e7fe7010b0 ''' 注意:把一段很長的數據update屢次,與一次update這段長數據,獲得的結果同樣 可是update屢次爲校驗大文件提供了可能。 '''
以上加密算法雖然依然很是厲害,但存在缺陷,即:經過撞庫(碰撞)能夠反解。因此,有必要對加密算法中添加自定義key(加鹽)再來作加密。
import hashlib m=hashlib.md5() m.update('world'.encode('utf8')) #7d793037a0760186574b0282f2f435e7 print (m.hexdigest()) x = hashlib.md5('天王蓋地虎'.encode('utf8')) x.update('world'.encode('utf8')) #26d7f494fd36ebcb1572fd41e5305b67 print (x.hexdigest())
import hashlib passwds=[ '123456', '96875643', 'qweasd321', 'qaz987321', '741852asd', 'zxc654123', ] 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='6d57314243f721a1bbddb9ca405f285d' #截取加密後的密文進行撞庫(好比說密碼是qaz987321) break_code(cryptograph,make_passwd_dic(passwds))
python 還有一個 hmac 模塊,它內部對咱們建立 key 和 內容 進行進一步的處理而後再加密:
import hmac h = hmac.new('天王蓋地虎'.encode('utf8')) h.update('hello'.encode('utf8')) print (h.hexdigest())#1abaae8f65f68f2695a8545c5bc8e738 #要想保證hmac最終結果一致,必須保證: #1:hmac.new括號內指定的初始key同樣 #2:不管update多少次,校驗的內容累加到一塊兒是同樣的內容
os模塊是與操做系統交互的一個接口
import os BASE=os.path.dirname(__file__) path=os.path.join(BASE,'dbpath') os.getcwd() #獲取當前工做目錄,即當前python腳本工做的目錄路徑 os.chdir("dbpath") #改變當前腳本工做目錄;至關於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(path+r'\test.py') # 刪除一個文件 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.popen(command[, mode[, bufsize]]) # 方法用於從一個命令打開一個管道。 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的大小 #========================================== os.walk() #方法是一個簡單易用的文件、目錄遍歷器,能夠幫助咱們高效的處理文件、目錄方面的事情。 #os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])參數 #top -- #是你所要遍歷的目錄的地址, 返回的是一個三元組(root,dirs,files)。 #root 所指的是當前正在遍歷的這個文件夾的自己的地址 #dirs 是一個 list ,內容是該文件夾中全部的目錄的名字(不包括子目錄) #files 一樣是 list , 內容是該文件夾中全部的文件(不包括子目錄) #topdown -- 可選, 爲 True,則優先遍歷 top 目錄,不然優先遍歷 top 的子目錄(默認爲開啓)。若是 topdown 參數爲 True,walk 會遍歷top文件夾,與top 文件夾中每個子目錄。 #onerror -- 可選, 須要一個 callable 對象,當 walk 須要異常時,會調用。 #followlinks -- 可選, 若是爲 True,則會遍歷目錄下的快捷方式(linux 下是 symbolic link)實際所指的目錄(默認關閉)。
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__))))
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 返回操做系統平臺名稱
#=========知識儲備========== #進度條的效果 [# ] [## ] [### ] [#### ] #指定寬度 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
def __progress(self, recv_size, data_size, width=70): ''' =========進度條========== # data_size = 9292 # 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''' percent = float(recv_size) / float(data_size) 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='') #================================== self.__progress(receive_size, file_size)#接受大小,總文件大小
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.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)
import random def make_code(n): res='' for i in range(n): s1=chr(random.randint(65,90)) #chr 表明參照ASCII表 轉成對應字符 s2=str(random.randint(0,9)) res+=random.choice([s1,s2]) #取隨機數拼湊 return res print(make_code(4))