import 單文件 from dir import file 目錄下文件 若是有相同的名稱,能夠採用別名的方式 from dir import file as rename.file pip3 requests install 源碼下載後會出現STEUP.PY文件,而後PYTHON STEUP.PY INSTALL 注意依賴關係
__name__是什麼鬼html
# !/usr/bin/env python # _*_coding:utf-8_*_ # Author:Joker """ my 註釋 """ # print(__doc__) # 獲取文件註釋 # print(__cached__) # 字節碼路徑 pyc # print(__file__) # 當前運行的py的路徑,若是你跳到路徑執行,就只顯示文件名 import os print(os.path.abspath(__file__)) # 永遠的絕對路徑 print(os.path.dirname(os.path.abspath(__file__))) # 上一級目錄 import sys sys.path.append(os.path.dirname(os.path.abspath(__file__))) # 上級目錄添加到變量 import s2 print(s2.__package__) # 包位置 # /Users/liqianlong/Desktop/Django project/kkk/s6-python-develop/day21-模塊&包&--file--&開發規範 print(__name__) # __main__ 執行當前文件時,當前文件的特殊變量__name__ == '__main__'
#!/usr/bin/env python #_*_coding:utf-8_*_ # os模塊 # os模塊是與操做系統交互的一個接口 ''' os.walk() 顯示目錄下全部文件和子目錄以元祖的形式返回,第一個是目錄,第二個是文件夾,第三個是文件 open(r'tmp\inner\file',w) 建立文件 os.getcwd() 獲取當前工做目錄,即當前python腳本工做的目錄路徑 能夠先記錄當前文件目錄 os.chdir("dirname") 改變當前腳本工做目錄;至關於shell下cd os.curdir 返回當前目錄: ('.') 沒什麼用 os.pardir 獲取當前目錄的父目錄字符串名:('..') 沒什麼用 os.makedirs('dirname1/dirname2') 可生成多層遞歸目錄 dirname1若是存在就在下面建立,不存在都建立,若是都存在就報錯,可經過 修改裏面exist_ok=ok來解決這個報錯 os.removedirs('dirname1') 若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推, 可是若目錄不爲空,首先你要先刪除文件,否則報錯 os.mkdir('dirname') 生成單級目錄;至關於shell中mkdir dirname os.rmdir('dirname') 刪除單級空目錄,若目錄不爲空則沒法刪除,報錯;至關於shell中rmdir dirname os.listdir('dirname') 列出指定目錄下的全部文件和子目錄,包括隱藏文件,並以列表方式打印 os.remove() 刪除一個文件 os.rename("oldname","newname") 重命名文件/目錄 os.stat('path/filename') 獲取文件/目錄信息 os.sep 輸出操做系統特定的路徑分隔符,win下爲"\",Linux下爲"/" os.linesep 輸出當前平臺使用的行終止符,win下爲"\t\n",Linux下爲"\n" os.pathsep 輸出用於分割文件路徑的字符串 win下爲;,Linux下爲: os.name 輸出字符串指示當前使用平臺。win->'nt'; Linux->'posix' os.system("bash command") 運行shell命令,直接顯示 os.popen("bash command) 運行shell命令,獲取執行結果 print(ret.read()) 這樣讀取出來popen的結果 os.environ 獲取系統環境變量 os.path 括號內pathn就是文件夾和文件 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[, ...]]) 將多個路徑組合後返回,第一個絕對路徑以前的參數將被忽略 print(os.path.join(os.getcwd(),'filename')) os.path.getatime(path) 返回path所指向的文件或者目錄的最後訪問時間 os.path.getmtime(path) 返回path所指向的文件或者目錄的最後修改時間 os.path.getsize(path) 返回path的大小 ''' # 注意:os.stat('path/filename') 獲取文件/目錄信息 的結構說明 ''' stat 結構: st_mode: inode 保護模式 st_ino: inode 節點號。 st_dev: inode 駐留的設備。 st_nlink: inode 的連接數。 st_uid: 全部者的用戶ID。 st_gid: 全部者的組ID。 st_size: 普通文件以字節爲單位的大小;包含等待某些特殊文件的數據。 st_atime: 上次訪問的時間。 st_mtime: 最後一次修改的時間。 st_ctime: 由操做系統報告的"ctime"。在某些系統上(如Unix)是最新的元數據更改的時間,在其它系統上(如Windows)是建立時間(詳細信息參見平臺的文檔)。 ''' # sys模塊 # sys模塊是與python解釋器交互的一個接口 ''' sys.argv 命令行參數List,第一個元素是程序自己路徑 #作權限用 sys.exit(n) 退出程序,正常退出時exit(0) #經常使用 sys.version 獲取Python解釋程序的版本信息 sys.maxint 最大的Int值 sys.path 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值 sys.platform 返回操做系統平臺名稱 ''' # import sys # # >python "2os&sys.py" egon somebody #程序執行方式 # print(sys.argv) #打印參數,0是"2os&sys.py"程序文件名字 1是egon 2是somebody # name = sys.argv[1] # password = sys.argv[2] # if name == 'egon' and password == 'somebody': # print('繼續執行程序') # else: # sys.exit('登錄失敗') # 添加環境變量 # import sys # sys.path.append('/root/dir/file') # 進度條 import sys import time def view_bar(num,total): rate = float(num) / total rate_num = int(rate * 100) r = '\r%s>%d%%' % ('='*num,rate_num) # \r回到當前行的首部位 sys.stdout.write(r) # 相對比print,就是沒有換行符 # sys.stdout.flush() # 輸出清空 if __name__ == '__main__': print( '\r%s>%d%%' % ('=',1)) print( '\r%s>%d%%' % ('=',2)) print( '\r%s>%d%%' % ('=',98)) print( '\r%s>%d%%' % ('=',100)) for i in range(1,101): time.sleep(0.3) view_bar(i,100) # %% 2個百分號表明一個站位符
# !/usr/bin/env python # _*_coding:utf-8_*_ # Author:Joker import time # print(time.time()) # 1531982635.617672 時間戳 1970年開始計數的 # print(time.ctime()) # Thu Jul 19 14:45:44 2018,當前時間 # print(time.ctime(time.time()-86400)) # Wed Jul 18 14:49:26 2018 時間戳轉化爲字符串時間 # print(time.gmtime()) # time.struct_time(tm_year=2018, tm_mon=7, tm_mday=19, tm_hour=6, tm_min=50, tm_sec=15, tm_wday=3, tm_yday=200, tm_isdst=0) # time_obj = time.gmtime() # print(time_obj.tm_year,time_obj.tm_mon) # 2018 7 注意下day的值,週一是0,並且是utc時間 # print(time.gmtime(time.time()-86400)) # 將時間戳轉換成struct_time格式 # time.struct_time(tm_year=2018, tm_mon=7, tm_mday=18, tm_hour=6, tm_min=53, tm_sec=37, tm_wday=2, tm_yday=199, tm_isdst=0) # print(time.localtime()) # 本地時間,按照服務器的時區 # time.struct_time(tm_year=2018, tm_mon=7, tm_mday=19, tm_hour=14, tm_min=56, tm_sec=14, tm_wday=3, tm_yday=200, tm_isdst=0) # time_obj = time.gmtime() # print(time.mktime(time_obj)) # 時間對象轉成時間戳 # 1531954699.0 # tm = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()) # 將struct_time格式轉化成指定的字符串格式 # print(tm) # 2018-07-19 15:02:11 # tm = time.strptime('2018-07-19','%Y-%m-%d') # 將字符串格式轉化成struct_time格式 # print(tm) # time.struct_time(tm_year=2018, tm_mon=7, tm_mday=19, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=200, tm_isdst=-1) import datetime # print(datetime.date.today()) # 2018-07-19,當前年月日 # print(datetime.date.fromtimestamp(time.time())) # 2018-07-19 將時間戳轉換成日期格式 # print(datetime.datetime.now()) # 2018-07-19 15:10:00.874436 當前時間 # current_time = datetime.datetime.now() # print(current_time.timetuple()) # 將字符串轉換爲struct_time格式 # time.struct_time(tm_year=2018, tm_mon=7, tm_mday=19, tm_hour=15, tm_min=11, tm_sec=30, tm_wday=3, tm_yday=200, tm_isdst=-1) # str_to_date = datetime.datetime.strptime('09/10/12','%d/%m/%y') # print(str_to_date) # 2012-10-09 00:00:00 將字符串轉換成日期格式 # 時間加減 # current_time = datetime.datetime.now() # 當前時間 # print(datetime.datetime.now() + datetime.timedelta(days=10)) # 2018-07-29 15:15:42.874593 比如今+10天 # print(datetime.datetime.now() - datetime.timedelta(days=10)) # 2018-07-09 15:16:55.388891 比如今-10天 # print(datetime.datetime.now() - datetime.timedelta(hours=10)) # 2018-07-19 05:18:23.341908 比如今-10小時 # 時間替換 # current_time = datetime.datetime.now() # 當前時間 # print(current_time.replace(2200,2,2)) # 2200-02-02 15:20:34.209528 # 時間比較 # current_time = datetime.datetime.now() # 當前時間 # old_time = current_time.replace(2017,5) # print(current_time > old_time) # True
# !/usr/bin/env python # _*_coding:utf-8_*_ # Author:Joker import shutil # f1 = open('隨便寫的.txt',encoding='utf-8') # f2 = open('lala','w',encoding='utf-8') # shutil.copyfileobj(f1,f2) # 將文件內容拷貝到另外一個文件中 # shutil.copyfile('隨便寫的.txt','haha') # 拷貝 # shutil.copymode('隨便寫的.txt','haha') # 僅拷貝權限,內容.組,用戶多是你拷貝時候的用戶 # shutil.copystat('隨便寫的.txt','haha') # 拷貝狀態信息 # shutil.copy('隨便寫的.txt','haha') # 拷貝文件和權限 # shutil.copy2('隨便寫的.txt','haha') # 拷貝文件和狀態信息 # shutil.copytree('目錄1','目錄2') # 遞歸拷貝文件,目錄名就能夠 # shutil.rmtree('目錄1') #刪除目錄,這裏寫當前目錄名就能夠 # shutil.move('file1','目錄') # 目錄名就能夠 # shutil.make_archive(base_name=,format=) # base_name 壓縮包的文件名,也能夠是壓縮包的路徑,若是隻是文件名,則保存至當前目錄,不然保存至指定路徑 # 如 WW,保存至當前目錄 # 如 /USER/WW 保存到/USER/目錄 # format 壓縮包種類,ZIP,TAR,BZTAR,GZTAR # root_dir 要壓縮的文件夾路徑 # owner 用戶,默認當前用戶 # group 組,默認當前組 # logger 用於記錄日誌,一般是logging.Logger對象 # shutil.make_archive('shuti','zip','壓縮文件的路徑便可') # ya import zipfile # # z = zipfile.ZipFile('da.zip','w') # z.write('lala') # print('乾點別的') # z.write('haha') # jie z = zipfile.ZipFile('da.zip','w') z.extractall() z.close() import tarfile # 壓縮 tar = tarfile.open('da.tar','w') tar.add('絕對lujing', arcname='bbs2.zip') tar.add('絕對lujing', arcname='cmdb.zip') tar.close() # 解壓 tar = tarfile.open('your.tar','r') tar.extractall() # 可設置解壓地址 tar.close()
#!/usr/bin/env python #_*_coding:utf-8_*_ # 序列化模塊 # 將本來的字典、列表等內容轉換成一個字符串的過程就叫作序列化 ''' 好比,咱們在python代碼中計算的一個數據須要給另一段程序使用,那咱們怎麼給? 如今咱們能想到的方法就是存在文件裏,而後另外一個python程序再從文件裏讀出來。 可是咱們都知道,對於文件來講是沒有字典這個概念的,因此咱們只能將數據轉換成字典放到文件中。 你必定會問,將字典轉換成一個字符串很簡單,就是str(dic)就能夠辦到了,爲何咱們還要學習序列化模塊呢? 沒錯序列化的過程就是從dic 變成str(dic)的過程。如今你能夠經過str(dic),將一個名爲dic的字典轉換成一個字符串, 可是你要怎麼把一個字符串轉換成字典呢? 聰明的你確定想到了eval(),若是咱們將一個字符串類型的字典str_dic傳給eval,就會獲得一個返回的字典類型了。 eval()函數十分強大,可是eval是作什麼的?e官方demo解釋爲:將字符串str當成有效的表達式來求值並返回計算結果。 BUT!強大的函數有代價。安全性是其最大的缺點。 想象一下,若是咱們從文件中讀出的不是一個數據結構,而是一句"刪除文件"相似的破壞性語句,那麼後果實在不堪設設想。 而使用eval就要擔這個風險。 因此,咱們並不推薦用eval方法來進行反序列化操做(將str轉換成python中的數據結構) ''' # 序列化的目的 # 一、以某種存儲形式使自定義對象持久化; # 二、將對象從一個地方傳遞到另外一個地方。 # 三、使程序更具維護性。 # 數據結構 --> 序列化 --> str # str --> 反序列化 --> 數據結構 d = {'1':'v'} print(str(d)) s = str(d) print(eval(s),type(s)) #eval不安全,remove rm操做太危險 # json 不是python發明的,全部的語言都在用,語言之間用字符串傳遞 # json 字符串 字典 列表能夠的 # json 模塊提供四個功能:dumps,dump,loads,load # 將PYTHON基本數據類型轉化爲字符串形式 import json ret_s = json.dumps(d) print(ret_s,type(ret_s)) # 將PYTHON字符串形式轉化成基本數據類型 ret_d = json.loads(ret_s) print(ret_d,type(ret_d)) import json # li = "['alex','eric']" 報錯,由於其餘語言的緣由,''在其餘語言裏面是字符 li = '["alex","eric"]' ret = json.loads(li) print(ret,type(ret)) # ['alex', 'eric'] <class 'list'> #注意字符串必須是一個雙引號,單引號就會報錯 f = open('json_file') d_s = f.read() print(json.loads(d_s)) f.close() # 小結 內存操做 #dumps 結構化的數據類型轉字符串 #loads 字符串轉結構化數據類型 結構化數據類型中的全部字符串必須是雙引號引用 # 寫回文件 dump load 操做文件跟序列化的關係 f = open('json_file','w') dic = {'k1':'v1','k2':'v2','k3':'v3'} json.dump(dic,f) # 先序列化,在寫文件 # f.write(json.dumps(dic)) #是先dumps轉成字符串在寫入文件 f.close() f = open('json_file') dic2 = json.load(f) # 打開文件,而後轉化成數據類型,load在你打開過程當中幫你loads了 print(dic2,type(dic2)) #直接就是一個字典類型,不須要轉化 f.close() # pickle 全部數據類型均可以,可是隻是Python自有的,並且是bytes(用於一種Python獨特狀態) # json & pickle模塊 # 用於序列化的兩個模塊 # json,用於字符串 和 python數據類型間(列表,字典)進行轉換 # pickle,用於python特有的類型 和 python的數據類型間進行轉換 # pickle模塊提供了四個功能:dumps、dump(序列化,存)、loads(反序列化,讀)、load (不只能夠序列化字典,列表...能夠把python中任意的數據類型序列化) # python 特有的元祖 會被json搞成列表 # set json不支持 tu = {1,2,3,4} # import json # print(json.dumps(tu)) #json不支持,因此這裏不支持 import pickle print(pickle.dumps(tu)) #bytes類型 pik_b = pickle.dumps(tu) print(pickle.loads(pik_b)) #轉回來 li = [1,2,3,4,5] pickle.dump(li,open('db','rb')) ret = pickle.load(open('db','rb')) print(ret,type(ret)) # [1,2,3,4,5] list # shelve模塊 # shelve也是python提供給咱們的序列化工具,比pickle用起來更簡單一些。 # shelve只提供給咱們一個open方法,是用key來訪問的,使用起來和字典相似 import shelve f = shelve.open('shelve_file') f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'} #直接對文件句柄操做,就能夠存入數據 f.close() import shelve f1 = shelve.open('shelve_file') existing = f1['key'] #取出數據的時候也只須要直接用key獲取便可,可是若是key不存在會報錯 f1.close() print(existing) #注意:這個模塊有個限制,它不支持多個應用同一時間往同一個DB進行寫操做。 # 因此當咱們知道咱們的應用若是隻進行讀操做,咱們可讓shelve經過只讀方式打開DB import shelve #只讀模式,就不會影響寫的人了 f = shelve.open('shelve_file', flag='r') existing = f['key'] f.close() print(existing) #注意:因爲shelve在默認狀況下是不會記錄待持久化對象的任何修改的, # 因此咱們在shelve.open()時候須要修改默認參數,不然對象的修改不會保存。 import shelve f1 = shelve.open('shelve_file') #沒有改 print(f1['key']) f1['key']['new_value'] = 'this was not here before' f1.close() f2 = shelve.open('shelve_file', writeback=True) #改了 print(f2['key']) f2['key']['new_value'] = 'this was not here before' f2.close() # 小結:writeback方式有優勢也有缺點。優勢是減小了咱們出錯的機率,而且讓對象的持久化對用戶更加的透明瞭; # 但這種方式並非全部的狀況下都須要,首先,使用writeback之後,shelf在open()的時候會增長額外的內存消耗, # 而且當DB在close()的時候會將緩存中的每個對象都寫入到DB,這也會帶來額外的等待時間。 # 由於shelve沒有辦法知道緩存中哪些對象修改了,哪些對象沒有修改,所以全部的對象都會被寫入。
# !/usr/bin/env python # _*_coding:utf-8_*_ # Author:Joker 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) # 讀取配置文件 conf = configparser.ConfigParser() conf.read('example.ini') print(conf.sections()) # 不會打印DEFAULT,打印節點 print(conf.defaults()) # OrderedDict([('compression', 'yes'), ('serveraliveinterval', '45'), ('compressionlevel', '9'), ('forwardx11', 'yes')]) print(conf['bitbucket.org']['user']) # 增刪改查 # secs = config.sections() # print secs # options = config.options('group2') # print options # item_list = config.items('group2') # print item_list # val = config.get('group1','key') # val = config.getint('group1','key') # ########## 改寫 ########## # sec = config.remove_section('group1') # config.write(open('i.cfg', "w")) # sec = config.has_section('wupeiqi') # sec = config.add_section('wupeiqi') # config.write(open('i.cfg', "w")) # config.set('group2','k1',11111) # config.write(open('i.cfg', "w")) # config.remove_option('group2','age') # config.write(open('i.cfg', "w"))
#隨機數 import random #1.隨機小數 print(random.random()) #從0-1之間的小數 print(random.uniform(1,3)) #1-3之間的小數 #2.隨機整數 l = [] l.append(str(random.randint(0,9))) #0-9之間的隨機數 l.append(str(random.randint(0,9))) print(''.join(l)) #顯示97 print(l) #['9', '7'] print(random.randrange(1,4,2)) #也能夠用布長來作,這是打印1-4之間的奇數1 3 #3.隨機一個返回 print(random.choice([1,2,'b',4,'a',6])) #隨機選擇一個返回,[]()均可以 #4.隨機多個返回,返回的個數爲函數的第二個參數,本例中是返回3個 print(random.sample([1,2,'b',4,'a',6],3)) #返回3個,和以前的 返回的是列表 #5.打亂順序 l = list(range(100)) print(l) #正常順序 random.shuffle(l) print(l) #順序打亂 #寫一個驗證碼 #首先要有數字,其次要有字母,一共4位,能夠重複 #65-91是a-z,用chr()能夠轉成字母 #print(chr(90)) #普通版本 new_num_l = list(map(str,range(10))) #['0','1'...'9'] #用來存數字 alph_l = [chr(i) for i in range(65,91)] #列表推導式 用來存字母 new_num_l.extend(alph_l) #包含字母和數字 ret_l = [random.choice(new_num_l) for i in range(4)] #取得重複隨機 列表推導式 print(''.join(ret_l)) #由於是列表,因此join一下 ret = random.sample(new_num_l,4) #取得不重複隨機 print(''.join(ret)) # 寫成函數 def myrandom(): new_num_l = list(map(str,range(10))) alph_l = [chr(i) for i in range(97,123)] #列表推導式 new_num_l.extend(alph_l) ret_l = [random.choice(new_num_l) for i in range(4)] #列表推導式 return ''.join(ret_l) print(myrandom()) # def suiji(num): # return [random.choice(list(map(str,range(10))).extend([chr(i) for i in range(97,123)])) for j in range(num)] # x = suiji(4) # print(x)
# !/usr/bin/env python # _*_coding:utf-8_*_ # Author:Joker # 用於加密相關操做 import hashlib obj = hashlib.md5() obj.update(bytes('joker',encoding='utf-8')) ret = obj.hexdigest() print(ret) # 9facbf452def2d7efc5b5c48cdb837fa # 加鹽操做,本身的KEY obj = hashlib.md5(bytes('happy',encoding='utf-8')) obj.update(bytes('joker',encoding='utf-8')) ret = obj.hexdigest() print(ret) # c17ebd08acae8d7a822cec70da3fcf99
#!/usr/bin/python env #_*_coding:utf-8_*_ #collections模塊的用法 ''' 在內置數據類型(dict、list、set、tuple)的基礎上,collections模塊還提供了幾個額外的數據類型:Counter、deque、defaultdict、namedtuple和OrderedDict等。 1.namedtuple: 生成可使用名字來訪問元素內容的tuple 2.deque: 雙端隊列,能夠快速的從另一側追加和推出對象 3.Counter: 計數器,主要用來計數 4.OrderedDict: 有序字典 5.defaultdict: 帶有默認值的字典 ''' # 1.namedtuple (重點) from collections import namedtuple Ponit = namedtuple('Ponit',['x','y','z']) p = Ponit(1,2,5) print(p.x) print(p.y) print(p.z) # 2.deque ''' 使用list存儲數據時,按索引訪問元素很快,可是插入和刪除元素就很慢了,由於list是線性存儲,數據量大的時候,插入和刪除效率很低 deque是爲了高效實現插入和刪除操做的雙向列表,適合用於隊列和棧: ''' from collections import deque q = deque(['a', 'b', 'c']) q.append('x') q.appendleft('y') # print(q) #deque(['y', 'a', 'b', 'c', 'x']) # deque除了實現list的append()和pop()外,還支持appendleft()和popleft(),這樣就能夠很是高效地往頭部添加或刪除元素 # 3.OrderedDict (重點)消耗內存 ''' 使用dict時,Key是無序的。在對dict作迭代時,咱們沒法肯定Key的順序。 若是要保持Key的順序,能夠用OrderedDict: ''' from collections import OrderedDict d = dict([('a', 1), ('b', 2), ('c', 3)]) print(d) #d dict的Key是無序的 #{'a': 1, 'c': 3, 'b': 2} od = OrderedDict([('a', 1), ('b', 2), ('c', 3)]) print(od) #od OrderedDict的Key是有序的 #OrderedDict([('a', 1), ('b', 2), ('c', 3)]) # 注意,OrderedDict的Key會按照插入的順序排列,不是Key自己排序 od = OrderedDict() od['z'] = 1 od['y'] = 2 od['x'] = 3 od.keys() # 按照插入的Key的順序返回 #['z', 'y', 'x'] # 4.defaultdict (重點)(帶默認的字典,就是當這個) # 有以下值集合 [11,22,33,44,55,66,77,88,99,90...],將全部大於 66 的值保存至字典的第一個key中,將小於 66 的值保存至第二個key的值中。 # 普通代碼,須要判斷這個key,vales存在不存在 values = [11, 22, 33,44,55,66,77,88,99,90] my_dict = {} for value in values: if value>66: if my_dict.get('k1'): my_dict['k1'].append(value) else: my_dict['k1'] = [value] else: if my_dict.get('k2'): my_dict['k2'].append(value) else: my_dict['k2'] = [value] # 使用dict時,若是引用的Key不存在,就會拋出KeyError。若是但願key不存在時,返回一個默認值,就能夠用defaultdict: # 進階版本 會給返回默認的參數,用了匿名函數的原理 from collections import defaultdict values = [11, 22, 33,44,55,66,77,88,99,90] my_dict = defaultdict(list) for value in values: if value>66: my_dict['k1'].append(value) else: my_dict['k2'].append(value) print(my_dict['k1']) #匿名函數 from collections import defaultdict def func(): return 'N/A' my_dict = defaultdict(func) print(my_dict['k']) # 5.Counter # Counter類的目的是用來跟蹤值出現的次數。它是一個無序的容器類型,以字典的鍵值對形式存儲,其中元素做爲key, # 其計數做爲value。計數值能夠是任意的Interger(包括0和負數)。Counter類和其餘語言的bags或multisets很類似。 from collections import Counter c = Counter('abcdeabcdabcaba') print(c) # 輸出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1}) # http://www.cnblogs.com/Eva-J/articles/7291842.html print('aaab'.count('a'))
# !/usr/bin/env python # _*_coding:utf-8_*_ # Author:Joker #!/usr/bin/env python #_*_coding:utf-8_*_ #linux 上調用python腳本 #os.system輸出命令結果到屏幕,返回命令執行狀態 #os.popen("dir") 返回內存對象,須要單獨去取一下 #os.popen("dir").read() 保存命令的執行結果輸出,可是不返回執行狀態 # #py 2.7 from only linxu 2.7.... #commands = = == = commands.getstatusoutput("dir") 返回執行狀態和結果 #print(res[0]) (res[1]) #subprocess python 3.5 ___run import subprocess # subprocess.run(["df","-h"]) # subprocess.run(["df","-h","|","grep","sda1"]) 命令執行會報錯,由於加上管道符他解決不了 # subprocess.run(["df -h | grep sda1",shell=True]) 不須要python解析這個字符串,傳給linux本身去解析 #os.system = = = subprocess.call("df -h",shell=True)輸出命令結果到屏幕,返回命令執行狀態 #subprocess.checkcall("df -h",shell=True)若是報錯就拋出異常,也是返回狀態 #subprocess.getstatusoutput("df -h",shell=True)返回執行狀態和結果 ==== commands.getstatusoutput("dir") #subprocess.getoutput("df -h",shell=True)返回結果= = =os.popen("dir") # #subprocess.Popen("ifconfig|grep 192",shell=True,subprocess.PIPE) pipe 管道意思 #res.stdout.read() 標準輸出 #subprocess.Popen("dddd",shell=True,subprocess.PIPE,stderr=subprocess.PIPE) #res.stderr.read() 標準錯誤 #subprocess.Popen("sleep30:echo 'hello'",shell=True,subprocess.PIPE,stderr=subprocess.PIPE) #print(res.poll()) 這個是返回執行的狀態,執行完了返回0沒有執行返回None #print(res.wait()) 等待返回結果 #terminate()殺掉所啓動的進程 #subprocess.Popen("sleep30:echo 'hello'",shell=True,subprocess.PIPE,stderr=subprocess.PIPE) #res.terminate() #res.stdout.read() 是沒有結果的,由於在上一個命令進程殺掉了 #communicate()等待任務結束 忘了他吧 #subprocess.Popen(['python3'],shell=True,subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE) #res.stdin.write(b"print(1)") #res.stdin.write(b"print(2)") #res.communicate() #cwd新啓動的shell環境默認在哪一個地方 #subprocess.Popen(['pwd'],shell=True,subprocess.PIPE,cwd="/tmp") #res.stdout.read() #subprocess 交互輸入密碼 #subprocess.Popen("sudo apt-get install vim",shell=True) 環境亂了 #echo "pwd" | sudo -S apt-get install vim -S從標準輸入讀取密碼 #subprocess.Popen("echo 'pwd' | sudo -S apt-get install vim ",shell=True) 經過python能夠
''' 1.字符組:[0-9][a-z][A-Z] 在同一個位置可能出現的各類字符組成了一個字符組,在正則表達式中用[]表示 字符分爲不少類,好比數字、字母、標點等等。 假如你如今要求一個位置"只能出現一個數字",那麼這個位置上的字符只能是0、一、2...9這10個數之一。 能夠寫成這種 [0-5a-eA-Z] 取範圍的匹配 2.字符 . 匹配除換行符之外的任意字符 \w 匹配字母或數字或下劃線 \s 匹配任意的空白符 \d 匹配數字 \n 匹配一個換行符 \t 匹配一個製表符 \b 匹配一個單詞的結尾 ^ 匹配字符串的開始 $ 匹配字符串的結尾 \W 匹配非字母或數字或下劃線 \D 匹配非數字 \S 匹配非空白符 a|b 匹配字符a或字符b () 匹配括號內的表達式,也表示一個組 [...] 匹配字符組中的字符 [^...] 匹配除了字符組中字符的全部字符 3.量詞 量詞 用法說明 * 重複零次或更屢次 + 重複一次或更屢次 ? 重複零次或一次 {n} 重複n次 {n,} 重複n次或更屢次 {n,m} 重複n到m次 4. .^$ 正則 待匹配字符 匹配結果 說明 海. 海燕海嬌海東 海燕海嬌海東 匹配全部"海."的字符 ^海. 海燕海嬌海東 海燕 只從開頭匹配"海." 海.$ 海燕海嬌海東 海東 只匹配結尾的"海.$" 5.*+?{} 正則 待匹配字符 匹配結果 說明 李.? 李傑和李蓮英和李二棍子 李傑/李蓮/李二 ?表示重複零次或一次,即只匹配"李"後面一個任意字符 李.* 李傑和李蓮英和李二棍子 李傑和李蓮英和李二棍子 *表示重複零次或屢次,即匹配"李"後面0或多個任意字符 李.+ 李傑和李蓮英和李二棍子 李傑和李蓮英和李二棍子 +表示重複一次或屢次,即只匹配"李"後面1個或多個任意字符 李.{1,2} 李傑和李蓮英和李二棍子 李傑和/李蓮英/李二棍 {1,2}匹配1到2次任意字符 注意:前面的*,+,?等都是貪婪匹配,也就是儘量匹配,後面加?號使其變成惰性匹配 正則 待匹配字符 匹配結果 說明 李.*? 李傑和李蓮英和李二棍子 李/李/李 惰性匹配 6.字符集[][^] 正則 待匹配字符 匹配結果 說明 李[傑蓮英二棍子]* 李傑和李蓮英和李二棍子 李傑/李蓮英/李二棍子 表示匹配"李"字後面[傑蓮英二棍子]的字符任意次 李[^和]* 李傑和李蓮英和李二棍子 李傑/李蓮英/李二棍子 表示匹配一個不是"和"的字符任意次 [\d] 456bdha3 4/5/6/3 表示匹配任意一個數字,匹配到4個結果 [\d]+ 456bdha3 456/3 表示匹配任意個數字,匹配到2個結果 7.分組()或|和[^] 身份證號碼是一個長度爲15或18個字符的字符串,若是是15位則所有🈶️數字組成,首位不能爲0;若是是18位,則前17位所有是數字,末位多是數字或x,下面咱們嘗試用正則來表示: 正則 待匹配字符 匹配結果 說明 ^[1-9]\d{13,16}[0-9x]$ 110101198001017032 110101198001017032 表示能夠匹配一個正確的身份證號 ^[1-9]\d{13,16}[0-9x]$ 1101011980010170 1101011980010170 表示也能夠匹配這串數字,但這並非一個正確的身份證號碼,它是一個16位的數字 ^[1-9]\d{14}(\d{2}[0-9x])?$ 1101011980010170 False 如今不會匹配錯誤的身份證號了()表示分組,將\d{2}[0-9x]分紅一組,就能夠總體約束他們出現的次數爲0-1次 ^([1-9]\d{16}[0-9x]|[1-9]\d{14})$ 110105199812067023 110105199812067023 表示先匹配[1-9]\d{16}[0-9x]若是沒有匹配上就匹配[1-9]\d{14} 8.轉義符\ 在正則表達式中,有不少有特殊意義的是元字符,好比\d和\s等,若是要在正則中匹配正常的"\d"而不是"數字"就須要對"\"進行轉義,變成'\\'。 在python中,不管是正則表達式,仍是待匹配的內容,都是以字符串的形式出現的,在字符串中\也有特殊的含義,自己還須要轉義。因此若是匹配一次"\d",字符串中要寫成'\\d',那麼正則裏就要寫成"\\\\d",這樣就太麻煩了。這個時候咱們就用到了r'\d'這個概念,此時的正則是r'\\d'就能夠了。 正則 待匹配字符 匹配結果 說明 d \d False 由於在正則表達式中\是有特殊意義的字符,因此要匹配\d自己,用表達式\d沒法匹配 \\d \d True 轉義\以後變成\\,便可匹配 "\\\\d" '\\d' True 若是在python中,字符串中的'\'也須要轉義,因此每個字符串'\'又須要轉義一次 r'\\d' r'\d' True 在字符串以前加r,讓整個字符串不轉義 9,貪婪匹配 貪婪匹配:在知足匹配時,匹配儘量長的字符串,默認狀況下,採用貪婪匹配 正則 待匹配字符 匹配結果 說明 <.*> <script>...<script> <script>...<script> 默認爲貪婪匹配模式,會匹配儘可能長的字符串 <.*?> r'\d' <script>/<script> 加上?爲將貪婪匹配模式轉爲非貪婪匹配模式,會匹配儘可能短的字符串 幾個經常使用的非貪婪匹配Pattern *? 重複任意次,但儘量少重複 +? 重複1次或更屢次,但儘量少重複 ?? 重複0次或1次,但儘量少重複 {n,m}? 重複n到m次,但儘量少重複 {n,}? 重複n次以上,但儘量少重複 .*?的用法 . 是除換行符外任意字符 * 是取 0 至 無限長度 ? 是非貪婪模式。 何在一塊兒就是 取儘可能少的任意字符,通常不會這麼單獨寫,他大多用在: .*?x 就是取前面任意長度的字符,直到一個x出現 ''' # [] 中括號裏面若是是特殊意義字符就會變成普通的,好比[.*?]
#!/usr/bin/python env #_*_coding:utf-8_*_ import re #re模塊的用法 ret = re.findall('a', 'eva egon yuan') # 返回全部知足匹配條件的結果,放在列表裏 print(ret) #結果 : ['a', 'a'] ret = re.search('a', 'eva egon yuan').group() print(ret) #結果 : 'a' # 函數會在字符串內查找模式匹配,只到找到第一個匹配而後返回一個包含匹配信息的對象,該對象能夠 # 經過調用group()方法獲得匹配的字符串,若是字符串沒有匹配,則返回None。 ret = re.match('a', 'abc').group() # 同search,不過盡在字符串開始處進行匹配,若是沒有GROUP只是對象 print(ret) #結果 : 'a' ret = re.split('[ab]', 'abcd') # 先按'a'分割獲得''和'bcd',在對''和'bcd'分別按'b'分割 print(ret) # ['', '', 'cd'] ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1)#將數字替換成'H',參數1表示只替換1個 print(ret) #evaHegon4yuan4 ret = re.subn('\d', 'H', 'eva3egon4yuan4')#將數字替換成'H',返回元組(替換的結果,替換了多少次) print(ret) obj = re.compile('\d{3}') #將正則表達式編譯成爲一個 正則表達式對象,規則要匹配的是3個數字 ret = obj.search('abc123eeee') #正則表達式對象調用search,參數爲待匹配的字符串 print(ret.group()) #結果 : 123 import re ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一個存放匹配結果的迭代器 print(ret) # <callable_iterator object at 0x10195f940> print(next(ret).group()) #查看第一個結果 print(next(ret).group()) #查看第二個結果 print([i.group() for i in ret]) #查看剩餘的左右結果 #注意: #1 findall的優先級查詢 import re ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com') print(ret) # ['oldboy'] 這是由於findall會優先把匹配結果組裏內容返回,若是想要匹配結果,取消權限便可 ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com') print(ret) # ['www.oldboy.com'] #2 split的優先級查詢,規則,匹配內容,分割個數 ret=re.split("\d+","eva3egon4yuan") print(ret) #結果 : ['eva', 'egon', 'yuan'] ret=re.split("(\d+)","eva3egon4yuan") print(ret) #結果 : ['eva', '3', 'egon', '4', 'yuan'] #3 SPLIT有名分割,無名分割 ret = 'joker aa joker bb' print(re.split('joker',ret,1)) # ['', ' aa joker bb'] print(re.split('j(oker)',ret,1)) # ['', 'oker', ' aa joker bb'] #在匹配部分加上()以後所切出的結果是不一樣的, #沒有()的沒有保留所匹配的項,可是有()的卻可以保留了匹配的項, #這個在某些須要保留匹配部分的使用過程是很是重要的。 #findall #直接返回一個列表 #正常的正則表達式 #可是隻會把分組裏的顯示出來 #search #返回一個對象 .group() #match #返回一個對象 .group()
''' 默認狀況下Python的logging模塊將日誌打印到了標準輸出中,且只顯示了大於等於WARNING級別的日誌, 這說明默認的日誌級別設置爲WARNING(日誌級別等級CRITICAL > ERROR > WARNING > INFO > DEBUG), 默認的日誌格式爲日誌級別:Logger名稱:用戶輸出消息。 ''' # import logging # logging.debug('debug message') # logging.info('info message') # logging.warning('warning message') # logging.error('error message') # logging.critical('critical message') # 靈活配置日誌級別,日誌格式,輸出位置: import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename='test.log', filemode='w') logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message') # 配置參數 ''' logging.basicConfig()函數中可經過具體參數來更改logging模塊默認行爲,可用參數有: filename:用指定的文件名建立FiledHandler,這樣日誌會被存儲在指定的文件中。 filemode:文件打開方式,在指定了filename時使用這個參數,默認值爲「a」還可指定爲「w」。 format:指定handler使用的日誌顯示格式。 datefmt:指定日期時間格式。 level:設置rootlogger(後邊會講解具體概念)的日誌級別 stream:用指定的stream建立StreamHandler。能夠指定輸出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默認爲sys.stderr。若同時列出了filename和stream兩個參數,則stream參數會被忽略。 format參數中可能用到的格式化串: %(name)s Logger的名字 %(levelno)s 數字形式的日誌級別 %(levelname)s 文本形式的日誌級別 %(pathname)s 調用日誌輸出函數的模塊的完整路徑名,可能沒有 %(filename)s 調用日誌輸出函數的模塊的文件名 %(module)s 調用日誌輸出函數的模塊名 %(funcName)s 調用日誌輸出函數的函數名 %(lineno)d 調用日誌輸出函數的語句所在的代碼行 %(created)f 當前時間,用UNIX標準的表示時間的浮 點數表示 %(relativeCreated)d 輸出日誌信息時的,自Logger建立以 來的毫秒數 %(asctime)s 字符串形式的當前時間。默認格式是 「2003-07-08 16:49:45,896」。逗號後面的是毫秒 %(thread)d 線程ID。可能沒有 %(threadName)s 線程名。可能沒有 %(process)d 進程ID。可能沒有 %(message)s用戶輸出的消息 ''' # *** ''' logging庫提供了多個組件:Logger、Handler、Filter、Formatter。Logger對象提供應用程序可直接使用的接口,Handler發送日誌到適當的目的地, Filter提供了過濾日誌信息的方法,Formatter指定日誌顯示格式。另外,能夠經過:logger.setLevel(logging.Debug)設置級別,固然,也能夠經過 fh.setLevel(logging.Debug)單對文件流設置某個級別。 ''' # logger對象配置 ''' import logging logger = logging.getLogger() # 建立一個handler,用於寫入日誌文件 fh = logging.FileHandler('test.log') # 再建立一個handler,用於輸出到控制檯 ch = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) ch.setFormatter(formatter) logger.addHandler(fh) #logger對象能夠添加多個fh和ch對象 logger.addHandler(ch) logger.debug('logger debug message') logger.info('logger info message') logger.warning('logger warning message') logger.error('logger error message') logger.critical('logger critical message') '''
一 paramiko模塊的安裝 在python3中 pip3 install paramiko 在python2中 pycrypto,因爲 paramiko 模塊內部依賴pycrypto,因此先下載安裝pycrypto #在python2中 pip3 install pycrypto pip3 install paramiko 注:若是在安裝pycrypto2.0.1時發生以下錯誤 command 'gcc' failed with exit status 1... 多是缺乏python-dev安裝包致使 若是gcc沒有安裝,請事先安裝gcc 二 SSHClient 連接執行批處理命令 2.1基於用戶名密碼鏈接: import paramiko # 建立SSH對象 ssh = paramiko.SSHClient() # 容許鏈接不在know_hosts文件中的主機 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 鏈接服務器 ssh.connect(hostname='120.92.84.249', port=22, username='root', password='xxx') # 執行命令 stdin, stdout, stderr = ssh.exec_command('df') # 獲取命令結果 result = stdout.read() print(result.decode('utf-8')) # 關閉鏈接 ssh.close() 2.2SSHClient 封裝 Transport import paramiko transport = paramiko.Transport(('120.92.84.249', 22)) transport.connect(username='root', password='xxx') ssh = paramiko.SSHClient() ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('df') res=stdout.read() print(res.decode('utf-8')) transport.close() SSHClient 封裝 Transport 2.3基於公鑰密鑰鏈接: 客戶端文件名:id_rsa 服務端必須有文件名:authorized_keys(在用ssh-keygen時,必須製做一個authorized_keys,能夠用ssh-copy-id來製做) import paramiko private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa') # 建立SSH對象 ssh = paramiko.SSHClient() # 容許鏈接不在know_hosts文件中的主機 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 鏈接服務器 ssh.connect(hostname='120.92.84.249', port=22, username='root', pkey=private_key) # 執行命令 stdin, stdout, stderr = ssh.exec_command('df') # 獲取命令結果 result = stdout.read() print(result.decode('utf-8')) # 關閉鏈接 ssh.close() 2.4SSHClient 封裝 Transport import paramiko private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa') transport = paramiko.Transport(('120.92.84.249', 22)) transport.connect(username='root', pkey=private_key) ssh = paramiko.SSHClient() ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('df') result=stdout.read() print(result.decode('utf-8')) transport.close() SSHClient 封裝 Transport 2.5基於私鑰字符串進行鏈接 import paramiko from io import StringIO key_str = """-----BEGIN RSA PRIVATE KEY----- MK7ydr+Q1+6/ujs6e8WsXt8HZMa/1khCVSbrf1MgACvZPSSSrDpVwaDTSjlRI4AL -----END RSA PRIVATE KEY-----""" private_key = paramiko.RSAKey(file_obj=StringIO(key_str)) transport = paramiko.Transport(('120.92.84.249', 22)) transport.connect(username='root', pkey=private_key) ssh = paramiko.SSHClient() ssh._transport = transport stdin, stdout, stderr = ssh.exec_command('df') result = stdout.read() print(result.decode('utf-8')) transport.close() 三 SFTPClient 用於鏈接遠程服務器並執行上傳下載 3.1基於用戶名密碼上傳下 import paramiko transport = paramiko.Transport(('120.92.84.249',22)) transport.connect(username='root',password='xxx') sftp = paramiko.SFTPClient.from_transport(transport) # 將location.py 上傳至服務器 /tmp/test.py sftp.put('/tmp/id_rsa', '/etc/test.rsa') # 將remove_path 下載到本地 local_path sftp.get('remove_path', 'local_path') transport.close() 3.2基於公鑰密鑰上傳下載 import paramiko private_key = paramiko.RSAKey.from_private_key_file('/tmp/id_rsa') transport = paramiko.Transport(('120.92.84.249', 22)) transport.connect(username='root', pkey=private_key ) sftp = paramiko.SFTPClient.from_transport(transport) # 將location.py 上傳至服務器 /tmp/test.py sftp.put('/tmp/id_rsa', '/tmp/a.txt') # 將remove_path 下載到本地 local_path sftp.get('remove_path', 'local_path') transport.close()
''' 題目:簡單主機批量管理工具 需求: 主機分組 主機信息配置文件用configparser解析 可批量執行命令、發送文件,結果實時返回,執行格式以下 batch_run -h h1,h2,h3 -g web_clusters,db_servers -cmd "df -h" batch_scp -h h1,h2,h3 -g web_clusters,db_servers -action put -local test.py -remote /tmp/ 主機用戶名密碼、端口能夠不一樣 執行遠程命令使用paramiko模塊 批量命令需使用multiprocessing併發 ''' import paramiko import os cmdlist=[] ftplist=[] class instructions: def __init__(self,user,pwd,host,port): self.user=user self.pwd=pwd self.host=host self.port=port def conn(self): transport = paramiko.Transport((self.host,self.port)) transport.connect(username=self.user,password=self.pwd) #ssh連接對象 ssh = paramiko.SSHClient() ssh._transport = transport cmdlist.append(ssh) #ftp連接對象 sftp = paramiko.SFTPClient.from_transport(transport) ftplist.append(sftp) def cmd(self,user_order): for ssh_i in cmdlist: stdin, stdout, stderr = ssh_i.exec_command(user_order) res = stdout.read()+stderr.read() print(res.decode('utf-8')) def ftp(self,client_file,server_file): for sftp_i in ftplist: sftp_i.put(client_file,server_file) def quit(self): for ssh_i in cmdlist: ssh_i.close() for sftp_i in ftplist: #不知道能不能關閉 sftp_i.close() cmdlist.clear() ftplist.clear() def ls(): for x in os.listdir(os.getcwd()): if os.path.isfile(x): print(x) if __name__ == '__main__': user='root' pwd='123456' host=['192.168.1.104','192.168.1.106'] port=22 while True: user_cmd=input('>>>:') if user_cmd == 'conn': for host_i in host: link=instructions(user,pwd,host_i,port) link.conn() print('%s-連接Ok' %host_i) while True: user_cmd = input('>>>:') user_cmd = user_cmd.split() if user_cmd[0] == 'ls': ls() elif user_cmd[0] == 'cmd': link.cmd(user_cmd[1]) elif user_cmd[0] == 'put': if os.path.isfile(user_cmd[1]): link.ftp(user_cmd[1],user_cmd[2]) else: print('沒有找到該%s文件'%user_cmd[1]) continue elif user_cmd[0] == 'quit': link.quit() break else: print('ls,cmd,put,quit') continue else: print('首先應該先連接!conn') continue break