1. 程式人生 > >程序、執行緒、鎖相關筆記

程序、執行緒、鎖相關筆記

day1:

淺拷貝:a=b 兩個列表id相同,用的是同一個堆和棧
深拷貝:a=copy.deepcopy(a) 兩個列表id不同,用的是不同的堆和棧

檢視工作管理員 : Shift+Ctrl+Esc

阻塞狀態:等待狀態,程式碼都沒有執行如input等待輸入時
就緒狀態:阻塞結束到執行之前
執行狀態:

程序(1.程序的概念:一個程式的一次執行

  2.匯入process模組:	from multiprocessing import Process  匯入的是multiprocessing中的process模組  process就是程序模組
建立程序       :	p=Process(target=程序體,args=(引數元組)

  3.程序子類繼承:

	from multiprocessing import Process
	import os

	class MyProcess(Process):
			def __init__(self,num):
    			super().__init__()
    			self.num = num


			def run(self):
    			self.num
    			print("當親程序為子程序  ,子程序ID為%d"%os.getpid())

	if __name__ == '__main__':
			print(os.getpid())
			for i in range(10):
    			m = MyProcess(5)
    			m.start()
	繼承multiprocessing包的Process模組,當啟動start()方法是,會在類中觸發run()方法建立子程序並呼叫



  4.程序池:
	程序池:有伺服器預先建立的一組子程序(https://blog.csdn.net/hello_bravo_/article/details/52528283)
		p=multiprocessing.Pool(程序池容量)
			p.apply_async(子程序	程序體,引數元組)    非同步執行程序(程序可同時執行)
    			p.apply(.....同上)		同步執行程序(執行完一個才能執行下一個)

	程序池中的子程序:程序池在伺服器啟動之初就建立好了,所以每個子程序都相對"乾淨",即它們沒有開啟不必要的檔案描述符(從父程序繼承而來)

		  	也不會錯誤地使用大塊的堆記憶體(從父程序複製得到)

	程序池Pool中的apply方法與apply_async的區別(https://www.jianshu.com/p/0a55507f9d9e?open_source=weibo_search)

		1.pool=Pool(3)   #建立程序池   括號中填程序池的程序容量   不填預設為4個

		2.apply(func,args):同步執行
			apply方法是阻塞的,意思就是等待當前子程序執行完畢後,在執行下一個程序。
			因為apply是阻塞的,所以進入子程序執行後,等待當前子程序執行完畢,在繼續執行下一個程序
			首先主程序開始執行,碰到子程序,作業系統切換到子程序,等待子程序執行結束後,在切換到另外一個子程序,直到所有子程序執行完畢。						然後在切換到主程序,執行剩餘的部分。

		3.apply_async:非同步執行
			apply_async是非同步非阻塞的,意思就是:不用等待當前程序執行完畢,隨時根據系統排程來進行程序切換。

			首先主程序開始執行,碰到子程序後,子程序執行,主程序說:讓我先執行個夠,等到作業系統進行程序切換的時候,在交給子程序執行。以為我們的
			程式太短,然而還沒等到作業系統進行程序切換,主程序就執行完畢了。
			想要子程序執行,就告訴主程序:你等著所有子程序執行完畢後,在執行剩餘部分。join()
	
		4.join()    (https://blog.csdn.net/qq_41020281/article/details/79561043)
			join所完成的工作就是執行緒同步,即主執行緒任務結束之後,進入阻塞狀態,一直等待其他的子執行緒執行結束之後,主執行緒再終止
		
  5.程序間的通訊
	必須先例項化Queue類   使用例項化的物件實現程序間的通訊
	p=Queue(通訊容量)
	如果要放進程序體
	q.put('hello')	寫入
	print(q.get())	取出
	q.size()        檢測寫入幾個
	q.full()	檢測寫滿沒有  滿True
	q.empty()       空True 非空False

day2:

執行緒(1.執行緒的概念
2.執行緒和程序的區別
3.執行緒的建立
4.執行緒子類的繼承
5.執行緒間的全域性變數是共享的
6.執行緒互斥鎖【執行緒如果頻繁修改全域性變數,會對資料造成一定的誤差】)

建立執行緒(兩個方法:建立或類中繼承建立):import threading(匯入thread模組的包)
	  t=threading.Thread(target=zxc,args=(,))

互斥鎖:(https://blog.csdn.net/yanhuatangtang/article/details/75316644)
	from  threading import Lock
	m=Lock()
	n=m.acquire(False)    #上鎖  	引數為False時,執行緒沒取到共享變數也會繼續執行,因此要加上if n
					不寫引數預設(True),上鎖時取不到共享變數的執行緒會進入阻塞狀態,一直等待共享變數解鎖取到為止,這種寫法 不需要判斷if n
	if n:
		num+=1
		m.release()

協程:
協程的概念
複習迭代器
複習生成器
協程的編排(使用迭代器和生成器編輯的協程)
http://python.jobbole.com/86481/

生成器的編輯:(生成器中yield返回的值只能被迭代出來)
import time
def A():
while True:
print("=A=")
yield #記住這次執行到這,掛起函式,返回到迭代處,下次執行時從這裡開始繼續執行
time.sleep(1)
def B©:
while True:
print("=B=")
next(c())
time.sleep(1)
B(A())

列表推導式:
lists=[i for i in range(10)]

迭代器:
一般迭代生成器
next()
B(a)
或:
a=iter(迭代物件)
a.next()

greenlet:
from greenlet import greenlet
def A():

g2.switch()

def B():

g1.switch()
g1=greenlet(A)
g2=greenlet(B)
g1.switch()

單例
class Person(object):
__instanse = None
def new(cls,*asd,**sdf):
if cls.__instanse == None:
cls.__instanse = super().new(cls)
return cls.__instanse
def init(self):
print(“這是一個很寂寞的天”)
def start(self):
print(“下著有些傷心的雨”)
p=Person()
m=Person()
print(id§)
print(id(m))

程序執行緒總結(https://blog.csdn.net/a2011480169/article/details/74370184)

day4

套接字:
是支援網路通訊的基本操作單元,可以看做是不同主機之間的程序進行雙向通訊的端點(可看作通訊兩方的一種約定)
通過套接字中的相關函式完成通訊過程(Socket=Ip address+ TCP/UDP + port)port:埠號
UDP(資料報套接字): SOCK_DGRAM
TCP(流式套接字): SOCK_STREAM

互動:(B:瀏覽器 C:客戶端 S:伺服器)
C/S: 客戶端、伺服器互動
B/S: 瀏覽器、伺服器互動

IP:
檢視IP:開啟cmd,打ipconfig
內網:不能上網
外網:能上網

網路埠號:

協議:
udp:使用者資料報協議:無連線的簡單的面向資料報的傳輸層協議(通訊時只負責傳送,是否接收並不負責,會發生丟包)

socket(from socket import *)socket.socket:

udp型別:使用者資料報協議:無連線的簡單的面向資料報的傳輸層協議(通訊時只負責傳送,是否接收並不負責)
	 通訊只有兩個客戶端:【傳送:udp_socket.sendto(send_data.encode("gb2312"),send_address
			       接收:get_data=udp_socket.recvfrom(1024))
			      】


	傳送:(核心:udp_socket.sendto(send_data.encode("gb2312"),send_address)):


		#建立socket型別:     1.UDP:資料報套接字    2.TCP:流式套接字
		#建立UDP使用 SOCK_DGRAM    資料報套接字
		#建立TCP使用 SOCK_STREAM   流式套接字
		udp_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  #建立一個UDP的socket  (通訊屬性,socket型別)
			#第一個引數:不同電腦間通訊選擇AF_INET(socket包中的一個屬性)
			#第二個引數:type 建立的socket的型別(建立UDP使用 SOCK_DGRAM資料報套接字  
			#建立TCP使用 SOCK_STREAM 流式套接字)
		send_address=('傳送方埠號',接收方埠號)  #繫結要傳送資料的IP和埠號 也就是接收方的IP地址和埠號 他是一個元組
		send_data(變數名)=input(‘請輸入要傳送的資料’)
		udp_socket.sendto(send_data.encode("gb2312"),send_address)	#傳送資料  使用UPD物件(dup_socket來發送資料
			#使用物件中的sendto方法 內建兩個引數
			#第一個引數是傳送的資料
			#第二個引數是接收方的IP地址和埠號
		udp_socket.close()	#關閉資源

	接收:(核心get_data=udp_socket.recvfrom(1024)):


		from socket import *
		udp_socket=socket(AF_INET,SOCK_DGRAM)
		#如果對方要給我發信息  那麼一定要知道我的IP地址和埠號
		#IP地址是已知的 埠號 
		#當前應繫結我當前程序的埠號
		#使用bind方法綁定當前程序的埠號和IP
		#內建一個引數 引數是一個元組
		address_family=("10.10.86.208",9988)
		udp_socket.bind(address_family)

		#接收資訊使用recvfrom方法 內建一個引數
		#引數是udp物件接收資料的最大值單位是位元組
		#然後recvfrom有一個返回值
		#返回值是一個元組
		#元組中有兩個元素 第一個元素是接收的資料 第二個元素還是一個元組(元組裡面是傳送方的IP和埠號)
		get_data=udp_socket.recvfrom(1024)
		print(get_data)
		#關閉資源
		udp_socket.close()
		udp_socket.bind()





tcp型別:傳輸控制協議:面向連線的協議(要連線也要斷開。不會丟包,沒傳送或接收到會報錯)
	通訊時有伺服器端(被動方)和客戶端(主動方)


	伺服器端:
		#編輯伺服器   (#1.轉被動;限制客戶端介面量  		listen(介面個數)
									listen():函式不會阻塞,它主要做的事情為,將該套接字和套接字對應的連線佇列長度告訴 												 Linux 核心,然後,listen()函式就結束。
             			#2.建立新socket;接收客戶端地址  	accept() 
    	     			#3.接收客戶端請求   			recv(接收位元組容量)
				#4.輸出請求				print(請求內容.解碼)
         				#5.傳送響應    				send(響應內容.轉碼)
             			#6.關閉新socket   			close()
			       )




	客戶端:
		#編輯客戶端	(#1.連線地址    connect((ip,埠號))
   					 #2.傳送請求     send(請求內容.轉碼)
   					 #3.接收響應     recv(接收位元組容量)
   					 #4.輸出響應     print(響應內容.解碼)
				 )



	三次握手四次揮手

		握手:
			客戶端向伺服器:【0請求連線】
				syn(0)---ack(1)
			伺服器向客戶端:【同意連線+1,0確定是否連線】
				+1,syn(0)---ack(1)
			客戶端向伺服器:【確定連線+1】
				+1,syn(0)---ack(1)

		揮手:fin(0)  ack(1)
			客戶端向伺服器:【0關閉】
				fin(0)---ack(1)
			伺服器向客戶端:【確認關閉+1,0客戶端關閉】
				+1,fin(0)---ack(1)
			伺服器向客戶端:【0請求獲取資源】
				fin(0)---ack(1)
			客戶端向伺服器:【送還資源+1,伺服器關閉資源】
				+1,fin(0)---ack(1)

new()new方法:(https://www.cnblogs.com/kex1n/p/5991249.html)

class object:
	@staticmethod # known case of __new__
	def __new__(cls, *more): # known special case of object.__new__
		""" T.__new__(S, ...) -> a new object with type S, a subtype of T """
		pass

1.__new__() 函式:
	只能用於從object繼承的新式類
	object將__new__()方法定義為靜態方法,並且至少需要傳遞一個引數cls,cls表示需要例項化的類,此引數在例項化時由Python直譯器自動提供。
	例項化物件的時候,呼叫__init__()初始化之前,先呼叫了__new__()方法
	__new__()必須要有返回值,返回例項化出來的例項
	需要注意的是,可以return父類__new__()出來的例項,也可以直接將object的__new__()出來的例項返回。


2.與__init__()init方法:
	__init__()有一個引數self,該self引數就是__new__()返回的例項
	__init__()在__new__()的基礎上可以完成一些其它初始化的動作,__init__()不需要返回值。
	若__new__()沒有正確返回當前類cls的例項,那__init__()將不會被呼叫,即使是父類的例項也不行。
	我們可以將類比作製造商,__new__()方法就是前期的原材料購買環節,__init__()方法就是在有原材料的基礎上,加工,初始化商品環節。

day5
python:
r:阻止轉義,原字串輸出

正則表示式:(https://www.cnblogs.com/xiaxiaoxu/p/8436795.html)
import re

方法:
	re.match()方法   引數2('',string).group() 從頭開始匹配
	re.search()方法 				   全域性查詢
	re.sub()方法     引數3('被替換的字串',‘替換的字串’,s(原字串))替換
	re.findall()	 引數2(正則,string)   符合條件的收入列表
			  	re.DOTALL :  
			  	re.M      :re.M表示將字串視為多行,從而^匹配每一行的行首,$匹配每一行的行尾
	re.split2(":|;",string)                             切割
普通轉義字元(背):
	\ : 轉義符(轉義一下)
	\d:匹配的是0--9任意一位數字
	\D: 匹配的是任意一位非數字  除了數字以外的任意字元都可以
	\w:匹配任意一位數字字母下劃線
	\W:匹配除了數字字母下劃線任意一位字元
	\s:匹配任意一位空白字元\r(換行?),\n(空行?),\t(製表符),\v(垂直製表符),\f(換頁符),空格
	\S:匹配任意一位非空白字元
	\b: 匹配字單詞的邊界
	\B: 匹配除單詞邊界以外的部分
	^或\A:放正則表示式第一位匹配字串串首的原子,放原子第一位是“非”的意思,其他位置就是一個原子
	$或\Z: 匹配字串串尾的原子放結尾,固定了最後一位
	?:匹配其前原子0次或一次()
	+ :匹配其前原子1次或多次(匹配不上,不成功,會報錯)
	* :匹配其前原子0次,1次或多次(沒有匹配字串,會匹配成功,結果為空,不會報錯)
	| :或,匹配兩個或多個選擇。與邏輯或相同
	. :匹配除換行符以外的任意字元
	.*: 無敵組合,沒碰到換行\n,一直匹配
	(): 整體表示一個原子    print(ret.group(2)) 輸出第二個括號返回的值
	  :
	  :二進位制
	  :八進位制
	  :十進位制
	  :十六進位制
	i:不區分大小寫

原子表[]:原子表裡面內建多個原子,在原子表中  每個原子都是平等的

貪婪匹配{}:在符合規則的情況下儘可能地多匹配
	{m}:匹配其前原子m次
	{m,}:匹配其前原子至少m次
	{,n}:匹配其原子最多n次
	{m,n}:匹配其前原子至少m次  匹配其前原子最多n次		 

\r:預設表示將輸出的內容返回到第一個指標,這樣的話,後面的內容會覆蓋前面的內容

day6
URL:(協議、域名、埠、路徑、錨)
U-協議http
R-域名www.com 可能跟埠
L-路徑:可能跟引數 引數後可能跟錨

web:
	編輯web伺服器:(response_header = "Server: DogBrother" + "\r\n"
				response_body = "hello 楊夢圓"
				response = response_start_line + response_header + "\r\n" + response_body
				new_socket.send(response.encode("gbk"))
			)

		#編輯web伺服器
		from socket import *
		tpc_server_socket = socket(AF_INET,SOCK_STREAM)
		tpc_server_socket.bind(('',8080))
		tpc_server_socket.listen(128)
		while True:
				new_socket,client_address = tpc_server_socket.accept()
				request_data = new_socket.recv(2048)
				response_start_line = "HTTP/1.1 200 OK" + "\r\n"
				response_header = "Server: DogBrother" + "\r\n"
				response_body = "hello 楊夢圓"
				response = response_start_line + response_header + "\r\n" + response_body
				new_socket.send(response.encode("gbk"))
				new_socket.close()
		tpc_server_socket.close()
	/:根目錄
	./:當前目錄
	../:上級目錄
	sum(num)函式傳參:複製

問題: 套接字
類方法靜態方法等
#\r,\n區別?
數字型別:4種
資料型別:6
join()

1.practice 29行(程序池)apply_sync(p_son)為什麼不用加括號,也不能寫target=      Thread(zxc())
2.程序池子類繼承?
3.Queue()  括號內表示的是什麼的容量,怎麼用
4.迭代器,生成器,裝飾器描述
5.淺拷貝,深拷貝
6.正則中的r

7.# ?????????
  # import re
  # line = "IF_MIB::=Counter32: 12345\nIF_MIB::=Counter32: 1234556";
  # result = re.findall(r'(?<=\:\s)\d+$', line, re.M)
  # print(result)

8.匹配\home關鍵字:

  re.findall(r"\\home","skjdfoijower \home   \homewer")

 結果:['\\home', '\\home']			多出來的\不能消掉麼

  匹配郵箱:
  匹配身份證:

9.listen(2):web伺服器中被動監聽2怎麼理解   (os.pid())

複習: 互斥鎖
程序池()