python拓展知識
類方法self的作用
未繫結的類方法:沒有self,通過類來引用方法返回一個未繫結方法物件。要呼叫它,你必須顯示地提供一個例項作為第一個引數。
繫結的例項方法:有self,通過例項訪問方法返回一個繫結的方法物件。Python自動地給方法繫結一個例項,所以我們呼叫它時不用再傳一個例項引數。
class Test(object): def func(self, message): print message obj = Test() x = obj.func # x 是一個繫結的方法物件, 不需要傳遞一個例項引數 x('hi') # fn 是一個未繫結的方法物件, 需要傳遞一個例項引數fn = Test.func fn(obj, 'hi') # fn('hi') # 錯誤的呼叫
type關鍵字
既可以檢視一個物件的型別 ,也可以建立類物件
檢視物件型別
a = 1 type(a) # <type 'int'> b = 'hello' type(b) # <type 'str'>
建立類物件
# 需要給一個引數來繫結類 def fn(self): print 'hello world' Hello = type('Hello', (object,), dict(hello=fn)) h= Hello() h.hello()
locals() 和 globals() 的區別
locals()返回區域性所有型別的變數的字典, globals()返回當前位置的全部全域性變數的字典
def test(arg): z = 1 print locals() test(4) # {'z': 1, 'arg': 4} print globals() # {'__builtins__': <module '__builtin__' (built-in)>, '__file__': '...', '__package__': None, 'test': <function test at 0x10ea970c8>, '__name__': '__main__', '__doc__': None}
字串title函式
將字串的每個單詞的首字母大寫,下劃線連線的單詞首字母也要大寫
str = 'my_str' print str.title() # My_Str
字串的rpartition函式
以某個分隔符將字串分成兩段,取最後一個匹配的位置的分隔符分隔,返回一個三元組(head, sep, tail)
print 'django.core.app'.rpartition('.') # ('django.core', '.', 'app')
python特殊函式__call__
所有的函式都是可呼叫物件,一個類例項也可以變成一個可呼叫物件,只需實現一個特殊方法__call__()
class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender def __call__(self, job): print 'My name is %s' % self.name print 'My gender is %s' % self.gender print 'My job is %s' % job p = Person('Bob', 'male') p('student')
python strip(), lstrip(), rstrip()函式
strip(): 返回字串的副本,並刪除前導和字尾字元
lstrip(): 返回字串的副本,刪除前導字元
rstrip(): 返回字串的副本,刪除字尾字元
str = ' hello ' print len(str) # 5 print len(str.strip()) # 7 str = 'rhellor' print str.strip('r') # hello print str.lstrip('r') # hellor print str.rstrip('r') # rhello
random.shuffle()
random.shuffle 將列表隨機排序
import random li = [1, 2, 3, 4, 5] random.shuffle(li) for i in li: print i
os.path模組
os.path.basename(path):獲取對應路徑下的檔名
os.path.abspath(path):返回path規範化的絕對路徑
os.path.split(path): 將path分割成目錄和檔名二元組返回
os.path.dirname(path): 返回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.splitext(path): 分離檔名與副檔名;預設返回(fname,fextension)元組,可做分片操作
os.path.getatime(path): 返回path所指向的檔案或者目錄的最後存取時間
os.path.getmtime(path): 返回path所指向的檔案或者目錄的最後修改時間
os.path.join(path1[, path2[, path3..]]):
os.path.join 可以傳入多個引數
- 會從第一個以”/”開頭的引數開始拼接,之前的引數全部丟棄;
- 以上一種情況為先。在上一種情況確保情況下,若出現”./”開頭的引數,會從”./”開頭的引數的上一個引數開始拼接。
import os print "1:", os.path.join('aaaa', '/bbbb', 'ccccc.txt') # 1: /bbbb/ccccc.txt print "2:", os.path.join('/aaaa', '/bbbb', '/ccccc.txt') # 2: /ccccc.txt print "3:", os.path.join('aaaa', './bbb', 'ccccc.txt') # 3: aaaa/./bbb/ccccc.txt
os.stat()
方法用於在給定的路徑上執行一個系統 stat 的呼叫
import os print os.stat("/root/python/zip.py") # (33188, 2033080, 26626L, 1, 0, 0, 864, 1297653596, 1275528102, 1292892895) print os.stat("/root/python/zip.py").st_mode #許可權模式 # 33188 print os.stat("/root/python/zip.py").st_ino #inode number # 2033080 print os.stat("/root/python/zip.py").st_dev #device # 26626 print os.stat("/root/python/zip.py").st_nlink #number of hard links # 1 print os.stat("/root/python/zip.py").st_uid #所有使用者的user id # 0 print os.stat("/root/python/zip.py").st_gid #所有使用者的group id # 0 print os.stat("/root/python/zip.py").st_size #檔案的大小,以位為單位 # 864 print os.stat("/root/python/zip.py").st_atime #檔案最後訪問時間 # 1297653596 print os.stat("/root/python/zip.py").st_mtime #檔案最後修改時間 # 1275528102 print os.stat("/root/python/zip.py").st_ctime #檔案建立時間 # 1292892895
socket.getaddrinfo()
函式原型:socket.getaddrinfo(host, port[, family[, socktype[, proto[, flags]]]])
返回值:[(family, socktype, proto, canonname, sockaddr)]有元組組成的列表,元組裡麵包含5個元素,其中sockaddr是(host, port)
- family:表示socket使用的協議簇,常用的協議簇包括AF_UNIX(本機通訊) 、AF_INET(TCP/IP協議簇中的IPv4協議)、AF_INET6(TCP/IP協議簇中的IPv4協議)。python的socket包中AF_UNIX=1, AF_INET=2, AF_INET6=10
- sockettype:表示socket的型別,常見的socket型別包括SOCK_STREAM(TCP流)、SOCK_DGRAM(UDP資料報)、SOCK_RAW(原始套接字),SOCK_STREAM=1, SOCK_DGRAM=2, SOCK_RAW=3
- proto:套介面所用的協議,若不指定,可用0,常用的協議有IPPROTO_TCP(6)和IPPTOTO_UDP(17),他們分別對應TCP傳輸協議、UDP傳輸協議
import socket print socket.getaddrinfo('www.baidu.com', 80) # [(2, 2, 17, '', ('180.97.33.108', 80)), (2, 1, 6, '', ('180.97.33.108', 80)), (2, 2, 17, '', ('180.97.33.107', 80)), (2, 1, 6, '', ('180.97.33.107', 80))]
struct模組pack和unpack
pack(fmt, v1, v2….):按照給定格式將資料封裝成字串(實際類似於c結構體的位元組流)
unpack(fmt, string ):按照給定格式解析位元組流,返回解析出的tuple
calcsize(fmt):計算給定的格式佔用多少位元組的記憶體
參考部落格: https://blog.csdn.net/w83761456/article/details/21171085
# coding: utf-8 import struct a = 'hello' b = 'world!' c = 2 d = 45.123 bytes = struct.pack('5s6sif', a, b, c, d) print bytes # helloworld!�}4B a, b, c, d = struct.unpack('5s6sif', bytes) print a, b, c, d # hello world! 2 45.1230010986
metaclass
允許你建立類或者修改類。換句話說,你可以把類看成是metaclass創建出來的“例項”。多喜歡自定義__new__方法
class Trick(FlyToSky):
pass
當我們在建立上面的類的時候,python做了如下的操作:
Trick中有__metaclass__這個屬性嗎?如果有,那麼Python會在記憶體中通過__metaclass__建立一個名字為Trick的類物件,也就是Trick這個東西。如果Python沒有找到__metaclass__,它會繼續在自己的父類FlyToSky中尋找__metaclass__屬性,並且嘗試以__metaclass__指定的方法建立一個Trick類物件。如果Python在任何一個父類中都找不到__metaclass__,它也不會就此放棄,而是去模組中搜尋是否有__metaclass__的指定。如果還是找不到,那就是使用預設的type來建立Trick。
那麼問題來了,我們要在__metaclass__中放置什麼呢?答案是可以建立一個類的東西,type,或者任何用到type或子類化type的東西都行。
參考部落格: https://www.cnblogs.com/piperck/p/5840443.html
class UpperAttrMetaClass(type): def __new__(mcs, class_name, class_parents, class_attr): attrs = ((name, value) for name, value in class_attr.items() if not name.startswith('__')) uppercase_attrs = dict((name.upper(), value) for name, value in attrs) return super(UpperAttrMetaClass, mcs).__new__(mcs, class_name, class_parents, uppercase_attrs) class Trick(object): __metaclass__ = UpperAttrMetaClass bar = 12 money = 'unlimited' print Trick.BAR print Trick.MONEY
設定守護程序 setDaemon(flag)
當一個程序啟動之後,會預設產生一個主執行緒,因為執行緒是程式執行流的最小單元,當設定多執行緒時,主執行緒會建立多個子執行緒,在python中,預設情況下(其實就是setDaemon(False)),主執行緒執行完自己的任務以後,就退出了,此時子執行緒會繼續執行自己的任務,直到自己的任務結束,當我們使用setDaemon(True)方法,設定子執行緒為守護執行緒時,主執行緒一旦執行結束,則全部執行緒全部被終止執行,可能出現的情況就是,子執行緒的任務還沒有完全執行結束,就被迫停止。
執行緒join方法
join所完成的工作就是執行緒同步,即主執行緒任務結束之後,進入阻塞狀態,一直等待其他的子執行緒執行結束之後,主執行緒再終止。
join有一個timeout引數:
- 設定守護執行緒,主執行緒對於子執行緒等待timeout的時間將會殺死該子執行緒,最後退出程式。所以說,如果有10個子執行緒,全部的等待時間就是每個timeout的累加和。簡單的來說,就是給每個子執行緒一個timeout的時間,讓他去執行,時間一到,不管任務有沒有完成,直接殺死。
- 沒有設定守護執行緒,主執行緒將會等待timeout的累加和這樣的一段時間,時間一到,主執行緒結束,但是並沒有殺死子執行緒,子執行緒依然可以繼續執行,直到子執行緒全部結束,程式退出。
參考部落格:https://www.cnblogs.com/cnkai/p/7504980.html
functools.wraps
在使用裝飾器時難免會損失一些東西,使用functools.wraps可以將原函式物件的指定屬性複製給包裝函式物件, 預設有 __module__、__name__、__doc__,或者通過引數選擇。
from functools import wraps def logged(func): @wraps(func) def with_logging(*args, **kwargs): print func.__name__ + " was called" return func(*args, **kwargs) return with_logging @logged def f(x): """does some math""" return x + x * x print f.__name__ # 不加wraps: with_logging # 加wraps: f print f.__doc__ # 不加wraps: None # 加wraps: does some math
孤兒程序和殭屍程序
什麼是孤兒程序?
一個父程序退出,而它的一個或多個子程序還在執行,那麼那些子程序將成為孤兒程序。孤兒程序將被init程序(程序號為1)所收養,並由init程序對它們完成狀態收集工作。
什麼是殭屍程序?
首先核心會釋放終止程序(呼叫了exit系統呼叫)所使用的所有儲存區,關閉所有開啟的檔案等,但核心為每一個終止子程序儲存了一定量的資訊。這些資訊至少包括程序ID,程序的終止狀態,以及該程序使用的CPU時間,所以當終止子程序的父程序呼叫wait或waitpid時就可以得到這些資訊。
而殭屍程序就是指:一個程序執行了exit系統呼叫退出,而其父程序並沒有為它收屍(呼叫wait或waitpid來獲得它的結束狀態)的程序。
任何一個子程序(init除外)在exit後並非馬上就消失,而是留下一個稱為殭屍程序的資料結構,等待父程序處理。這是每個子程序都必需經歷的階段。另外子程序退出的時候會向其父程序傳送一個SIGCHLD訊號。
如何避免殭屍程序?
- 通過signal(SIGCHLD, SIG_IGN)通知核心對子程序的結束不關心,由核心回收。如果不想讓父程序掛起,可以在父程序中加入一條語句:signal(SIGCHLD,SIG_IGN);表示父程序忽略SIGCHLD訊號,該訊號是子程序退出的時候向父程序傳送的。
- 父程序呼叫wait/waitpid等函式等待子程序結束,如果尚無子程序退出wait會導致父程序阻塞。waitpid可以通過傳遞WNOHANG使父程序不阻塞立即返回。
- 如果父程序很忙可以用signal註冊訊號處理函式,在訊號處理函式呼叫wait/waitpid等待子程序退出。
- 通過兩次呼叫fork。父程序首先呼叫fork建立一個子程序然後waitpid等待子程序退出,子程序再fork一個孫程序後退出。這樣子程序退出後會被父程序等待回收,而對於孫子程序其父程序已經退出所以孫程序成為一個孤兒程序,孤兒程序由init程序接管,孫程序結束後,init會等待回收。
參考部落格:https://www.cnblogs.com/Anker/p/3271773.html
select、poll、epoll三者的區別
為何使用select 單程序實現併發?
因為一個程序實現多併發比多執行緒是實現多併發的效率還要高,因為啟動多執行緒會有很多的開銷,而且CPU要不斷的檢查每個執行緒的狀態,確定哪個執行緒是否可以執行。
那麼單程序是如何實現多併發的呢?
之前的socket一個程序只能接收一個連線,當接收新的連線的時候產生阻塞,因為這個socket程序要先和客戶端進行通訊,二者是彼此互相等待的【客戶端發一條訊息,服務端收到,客戶端等著返回....服務端等著接收.........】一直在阻塞著,這個時候如果再來一個連線,要等之前的那個連線斷了,這個才可以連進來。也就是說用基本的socket實現多程序是阻塞的。為了解決這個問題採用每來一個連線產生一個執行緒,是不阻塞了,但是當執行緒數量過多的時候,對於cpu來說開銷和壓力是比較大的。
客戶端發起一個連線,會在服務端註冊一個檔案控制代碼,服務端會不斷輪詢這些檔案控制代碼的列表,主程序和客戶端建立連線而沒有啟動執行緒,這個時候主程序和客戶端進行互動,其他的客戶端是無法連線主程序的,為了實現主程序既能和已連線的客戶端收發訊息,又能和新的客戶端建立連線,就把輪詢變的非常快(死迴圈)去刷客戶端連線進來的檔案控制代碼的列表,只要客戶端發訊息了,服務端讀取了訊息之後,有另一個列表去接收給客戶端返回的訊息,也不斷的去刷這個列表,刷出來後返回給客戶端,這樣和客戶端的這次通訊就完成了,但是跟客戶端的連線還沒有斷,但是就進入了下一次的輪詢。
三者區別
select:單程序實現併發
poll: 它和select在本質上沒有多大差別,但是poll沒有最大檔案描述符數量的限制。
epoll: 直到Linux2.6才出現了由核心直接支援的實現方法,那就是epoll,它幾乎具備了之前所說的一切優點,被公認為Linux2.6下效能最好的多路I/O就緒通知方法, epoll可以同時支援水平觸發和邊緣觸發, epoll同樣只告知那些就緒的檔案描述符,而且當我們呼叫epoll_wait()獲得就緒檔案描述符時,返回的不是實際的描述符,而是一個代表 就緒描述符數量的值,你只需要去epoll指定的一個數組中依次取得相應數量的檔案描述符即可,這裡也使用了記憶體對映(mmap)技術,這樣便徹底省掉了 這些檔案描述符在系統呼叫時複製的開銷, 另一個本質的改進在於epoll採用基於事件的就緒通知方式。在select/poll中,程序只有在呼叫一定的方法後,核心才對所有監視的檔案描 述符進行掃描,而epoll事先通過epoll_ctl()來註冊一個檔案描述符,一旦基於某個檔案描述符就緒時,核心會採用類似callback的回撥 機制,迅速啟用這個檔案描述符,當程序呼叫epoll_wait()時便得到通知。
水平觸發和邊緣觸發
水平觸發:select()和poll()將就緒的檔案描述符告訴程序後,如果程序沒有對其進行IO操作,那麼下次呼叫select()和poll() 的時候將再次報告這些檔案描述符,所以它們一般不會丟失就緒的訊息,這種方式稱為水平觸發。
邊緣觸發:只告訴程序哪些檔案描述符剛剛變為就緒狀態,它只說一遍,如果我們沒有采取行動,那麼它將不會再次告知,這種方式稱為邊緣觸發。
參考部落格:https://www.cnblogs.com/qianyuliang/p/6551553.html
atexit模組
atexit只定義了一個register函式用於註冊程式退出時的回撥函式,我們可以在這個回撥函式中做一些資源清理的操作
import atexit def exit0(*args, **kwarg): print 'exit0' for arg in args: print arg for item in kwarg.items(): print item def exit1(): print 'exit1' atexit.register(exit0, *[1, 2, 3], **{"a": 1, "b": 2, }) atexit.register(exit1) @atexit.register def exit2(): print 'exit2' # 回撥函式執行的順序與它們被註冊的順序剛才相反 # exit2 # exit1 # exit0 # 1 # 2 # 3 # ('a', 1) # ('b', 2)
shutil模組
高階的 檔案、資料夾、壓縮包處理模組
常用函式
copyfileobj(檔案1,檔案2):將檔案1的資料覆蓋copy給檔案2
copyfile(檔案1,檔案2):不用開啟檔案,直接用檔名進行覆蓋copy
copymode(檔案1,檔案2):之拷貝許可權,內容組,使用者,均不變
copystat(檔案1,檔案):只拷貝了許可權
copy(檔案1,檔案2):拷貝檔案和許可權都進行copy
copy2(檔案1,檔案2):拷貝了檔案和狀態資訊
copytree(源目錄,目標目錄):可以遞迴copy多個目錄到指定目錄下
rmtree(目標目錄):可以遞迴刪除目錄下的目錄及檔案
move(原始檔,指定路徑):遞迴移動一個檔案
make_archive():可以壓縮,打包檔案
psutil模組
psutil是一個跨平臺庫(http://pythonhosted.org/psutil/)能夠輕鬆實現獲取系統執行的程序和系統利用率(包括CPU、記憶體、磁碟、網路等)資訊。它主要用來做系統監控,效能分析,程序管理。它實現了同等命令列工具提供的功能,如ps、top、lsof、netstat、ifconfig、who、df、kill、free、nice、ionice、iostat、iotop、uptime、pidof、tty、taskset、pmap等。目前支援32位和64位的Linux、Windows、OS X、FreeBSD和Sun Solaris等作業系統
參考部落格:https://www.cnblogs.com/saneri/p/7528283.html
inspect模組
主要用處
- 對是否是模組、框架、函式進行型別檢查
- 獲取原始碼
- 獲取類或者函式的引數資訊
- 解析堆疊
常用函式
getargspec(func):返回一個命名元組ArgSpect(args, varargs, keywords, defaults),args是函式位置引數名列表,varargs是*引數名,keywords是**引數名,defaults是預設引數值的元組。
getmembers(object[, predicate]):返回一個包含物件的所有成員的(name, value)列表。返回的內容比物件的__dict__包含的內容多,原始碼是通過dir()實現的。predicate是一個可選的函式引數,被此函式判斷為True的成員才被返回。
getmodule(object):返回定義物件的模組
getsource(object):返回物件的原始碼
getsourcelines(object):返回一個元組,元組第一項為物件原始碼行的列表,第二項是第一行原始碼的行號
stack():第一列是物件名,第二列是當前指令碼檔名,第三列是行數,第四列是函式名,第五列是具體執行的程式。第一行是當前函式,第二行是父級函式,以此往上推
threading.local()
這個方法的特點用來儲存一個全域性變數,但是這個全域性變數只有在當前執行緒才能訪問,localVal.val = name這條語句可以儲存一個變數到當前執行緒,如果在另外一個執行緒裡面再次對localVal.val進行賦值,那麼會在另外一個執行緒單獨建立記憶體空間來儲存,也就是說在不同的執行緒裡面賦值 不會覆蓋之前的值,因為每個執行緒裡面都有一個單獨的空間來儲存這個資料,而且這個資料是隔離的,其他執行緒無法訪問
import threading # 建立全域性ThreadLocal物件: localVal = threading.local() localVal.val = "Main-Thread" def process_student(): print '%s (in %s)' % (localVal.val, threading.current_thread().name) def process_thread(name): #賦值 localVal.val = name process_student() t1 = threading.Thread(target=process_thread, args=('One',), name='Thread-A') t2 = threading.Thread(target=process_thread, args=('Two',), name='Thread-B') t1.start() t2.start() t1.join() t2.join() print localVal.val # One (in Thread-A) # Two (in Thread-B) # Main-Thread
logging模組
logging模組是Python內建的標準模組,主要用於輸出執行日誌,可以設定輸出日誌的等級、日誌儲存路徑、日誌檔案回滾等;相比print,具備如下優點:
- 可以通過設定不同的日誌等級,在release版本中只輸出重要資訊,而不必顯示大量的除錯資訊
- print將所有資訊都輸出到標準輸出中,嚴重影響開發者從標準輸出中檢視其它資料;logging則可以由開發者決定將資訊輸出到什麼地方,以及怎麼輸出
# 基本使用 import logging logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) logger.info("Start print log") logger.debug("Do something") logger.warning("Something maybe fail.") logger.info("Finish")
參考部落格:https://www.cnblogs.com/liujiacai/p/7804848.html
日誌高階版zipkin
參考部落格:https://blog.csdn.net/liumiaocn/article/details/80657943