目錄
- 異常處理
- socketserver
- 線程、進程
一、異常處理
try的工作原理是,當開始一個try語句后,python就在當前程序的上下文中作標記,這樣當異常出現時就可以回到這里,try子句先執行,接下來會發生什么依賴於執行時是否出現異常。
代碼示例:
while True: n1 = input('input a number: ') n2 = input('input a number: ') try: n1 = int(n1) n2 = int(n2) res = n1 + n2 print(res.sd) l = [1,2,3,4,] print(l[10]) d = {1:'a',2:'b'} print(d[3]) print('num:%s' %res) except ArithmeticError as e: #引用屬性錯誤 print('ArithmeticError') except IndexError as e: #下標錯誤 print('IndexError') except KeyError as e: #key錯誤 print('KeyError') except ValueError as e: #引用的值錯誤 print('ValueError',e) except Exception as e: #拋出絕大部分的錯誤 print('異常錯誤') print(e)
通過創建一個新的異常類,程序可以命名它們自己的異常。異常應該是典型的繼承自Exception類,通過直接或間接的方式。
#自定義異常 class DemoException(Exception): def __init__(self,msg): self.message = msg def __str__(self): return self.message a = 1 try: #如果不滿足該條件,拋出異常 assert a == 1 except DemoException as e: print(e) else: print('ok') #無論是否存在異常,都執行finally finally: print('over')
二、sokectserver
socketserver 是標准庫中一個高級別的模塊,用於簡化網絡客戶與服務器的實現。
1、要實現本模塊,必須定義一個繼承於基類BaseRequestHandler的處理程序類。BaseRequestHandler類的實例可以實現以下方法:
1、h.handle() 調用該方法執行實際的請求操作。調用該函數可以不帶任何參數,但是幾個實例變量包含有用的值。h.request包含請求,h.client_address包含客戶端地址,h.server包含調用處理程序的實例。對TCP之類的數據流服務,h.request屬性是套接字對象。對於數據報服務,它是包含收到數據的字節字符串。
2.h.setup()該方法在handle()之前調用。默認情況下,它不執行任何操作。如果希望服務器實現更多連接設置,可以在這里實現。
3.h.finish()調用本方法可以在執行完handle()之后執行清除操作。如果setup()和 handle()都不生成異常,則無需調用該方法。
2.服務器。要使用處理程序,必須將其插入到服務器對象。定義了四個基本的服務器類。
1、TCPServer 支持ipv4的TCP協議的服務器。
2、UDPServer 支持ipv4的UDP協議的服務器。
3、UnixStreamServer 使用UNIX域套接字實現面向數據流協議的服務器,集成自TCPserver。
4、UnixDatagramServer 繼承自UDPServer
四個服務器類的實例都有一下方法和變量:
1、s.socket 用於傳入請求的套接字對象
2、s.server_address 監聽服務器的地址
3、s.RequestHandleClass 傳遞給服務器構造函數並由用戶提供的請求處理程序類
4、s.server_forever() 處理無線的請求
5、s.shutdown() 停止server_forever()循環
6、s.fileno() 返回服務器套接字的整數文件描述符。該方法可以有效的通過輪詢操作實例
代碼實例
server端 #導入該模塊 import socketserver #定義一個類,繼承socketserver.BaseRequestHandler class Server(socketserver.BaseRequestHandler): def handle(self): #打印客戶端地址和端口 print('New connection:',self.client_address) #循環 while True: #接收客戶發送的數據 data = self.request.recv(1024) if not data:break#如果接收數據為空就跳出,否則打印 print('Client data:',data.decode()) self.request.send(data)#將收到的信息再發送給客戶端 if __name__ == '__main__’: host,port = '127.0.0.1’,8080 #定義服務器地址和端口 server = socketserver.ThreadingTCPServer((host,port),Server) #實現了多線程的socket通話 server.serve_forever()#不會出現在一個客戶端結束后,當前服務器端就會關閉或者報錯,而是繼續運行,與其他的客戶端繼續進行通話。 client端 import socket ip_port = ('127.0.0.1',8080) sk = socket.socket() sk.connect(ip_port) while True: raw = input('>> ').strip() sk.send(bytes(raw,'utf8')) msg = sk.recv(1024) print(str(msg,'utf8')) sk.close()
三、進程和線程
1、定義
進程是具有一定獨立功能的程序,關於某個數據集合上的一次運行活動。進程是系統進行資源分配和調度的一個獨立單位。
線程是進程的一個實體,是CPU調度和分配的基本單位,它是比進程更小的能夠獨立運行的基本單位。線程不擁有系統資源,但是可以和同屬一個進程的其他線程貢獻進程所擁有的全部資源。
2、關系
一個線程可以創建和銷毀另一個線程;同一個進程中的多個線程之間可以並發執行。
3、最大差別在於它們是不同的資源管理方式。進程有獨立的地址空間,一個進程崩潰后,不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但沒有單獨的地址空間。因此一個線程死掉等於整個進程死掉,多以多進程的程序要比多線程的程序強壯,但進程切換時耗費資源比較大。對於一些要求同事進行又要共享某些變量的並發操作,只能用線程,不能用進程。
Python threading模塊
threading提供了一個比thread模塊更高層的API來提供線程的並發性。這些線程並發運行並共享內存。
一、Thread的使用
目標函數可以實例化一個Thread對象,每個Thread對象代表着一個線程,可以通過start()方法,開始運行。
有兩種方式來創建線程:一種是通過繼承Thread類,重寫它的run方法;另一種是創建一個threading.Thread對象,在它的初始化函數(__init__)中將可調用對象作為參數傳入。
import threading import time def sayhi(num): print('running on nuber:%s' %num) time.sleep(3) if __name__ == '__main__': t1 = threading.Thread(target=sayhi,args=(1,)) t2 = threading.Thread(target=sayhi,args=(2,)) t1.start() t2.start() print(t1.getName()) print(t2.getName()) import threading import time def sayhi(num): print('running on nuber:%s' %num) time.sleep(3) if __name__ == '__main__’: t_list = [] for i in range(20): t = threading.Thread(target=sayhi,args=[i,]) t.start() t_list.append(t) for i in t_list: i.join() print('----done——')
threading模塊中的join函數
該函數的作用主要是阻塞進程直到線程執行完畢。通用的做法是啟動一批線程,最后join這些線程結束。
原理就是一次檢驗線程池中的線程是否結束,沒有結束就阻塞知道線程結束,如果結束則跳轉執行下一個線程的join函數。
end