簡答來一個demo來演示一下
import threading
import time
def sing():
for i in range(5):
print("正在唱歌")
time.sleep(1)
def dance():
for i in range(5):
print("正在跳舞")
time.sleep(1)
def main():
t1 = threading.Thread(target=sing) # sing是實例對象,而sing()是返回值
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
if __name__ == '__main__':
main()
查看正在運行的線程
import threading
import time
def test1():
for i in range(5):
print("test01---->{}".format(i))
time.sleep(1)
def test2():
for i in range(5):
print("test02---->{}".format(i))
time.sleep(1)
def main():
threading.Thread(target=test1).start()
threading.Thread(target=test2).start()
print(threading.enumerate()) # 查看當前線程個數
# [<_MainThread(MainThread, started 140312615470848)>, <Thread(Thread-1, started 140312584259328)>, <Thread(Thread-2, started 140312575866624)>]
if __name__ == '__main__':
main()
args元祖參數
args指定將來調用函數的時候傳遞什麼參數過去
import threading
import time
def test1(num):
num.append(18)
print(num)
def test2(num):
num.append(55)
print(num)
def main():
threading.Thread(target=test1,args=([11,11],)).start()
threading.Thread(target=test2,args=([10,19],)).start()
if __name__ == '__main__':
main()
互斥鎖
# 創建鎖
mutex = threading.Lock()
# 鎖定
mutex.acquire()
# 釋放
mutex.release()
使用互斥鎖解決資源競爭的問題
在有可能出現資源競爭的部分,全部用鎖套起來
import threading
import time
def test1(num):
# 上鎖
mutex.acquire()
num.append(18)
print(num)
# 解鎖
mutex.release()
def test2(num):
# 上鎖
mutex.acquire()
num.append(55)
print(num)
# 解鎖
mutex.release()
def main():
threading.Thread(target=test1,args=([11,11],)).start()
threading.Thread(target=test2,args=([10,19],)).start()
# 創建一個互斥鎖
mutex = threading.Lock()
if __name__ == '__main__':
main()
實現多任務udp聊天器
import threading
import socket
def send_data(socket):
while True:
send_data = input("請輸入您要發送的數據")
socket.sendto(send_data.encode("utf8"), ("127.0.0.1", 7788))
def revc_data(socket):
while True:
revc_data = socket.recvfrom(1024)
print(revc_data[0].decode("utf8"))
def main():
# 創建stock
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
# 綁定port
udp_socket.bind(("127.0.0.1",8899))
# 發送數據
# 接收數據
threading.Thread(target=send_data, args=(udp_socket,)).start()
threading.Thread(target=revc_data, args=(udp_socket,)).start()
if __name__ == '__main__':
main()
使用進程實現多任務
進程的問題就是:浪費資源
import multiprocessing
import time
def test1():
while True:
print("1-----")
time.sleep(1)
def test2():
while True:
print("2----")
time.sleep(1)
def main():
multiprocessing.Process(target=test1).start()
multiprocessing.Process(target=test2).start()
if __name__ == '__main__':
main()
通過Queue隊列進程間通信
隊列:先進先出
相關方法:
from multiprocessing import Queue
q = Queue # 初始化一個Queue對象,最多可以接收3條put信息
# put放入數據
q.put("xxxx")
# 判斷是否滿了
q.full()
# 判斷鎖否空了
q.empyt()
#取數據用get
q.get()
數據下載分析demo演示
import multiprocessing
def download_to_web(q):
# 網絡下載數據
data=[11,22,33,44]
for i in data:
q.put(i)
print("下載完成等待提取")
def analysis_data(q):
# 數據處理
lst = []
while True:
print("提取。。。。。")
data = q.get()
lst.append(data)
if q.empty():
break
# 模擬進行數據處理
print("數據處理完成")
def main():
# 創建一個隊列
q = multiprocessing.Queue()
# 把隊列當作實參進行參數傳遞
multiprocessing.Process(target=download_to_web,args=(q,)).start()
multiprocessing.Process(target=analysis_data,args=(q,)).start()
if __name__ == '__main__':
main()
進程池Pool
使用場景:
面對大量任務,可以重複利用進程,減少了一個創建和銷燬的所消耗的資源
相關方法:
import mutiprocessing import Pool
po = Pool(3)
po.apply_async(要調用的目標,傳遞給目標的元祖參數)
po.close() # 關閉進程池
po.join() # 阻塞主進程,等待進程池跑完在解堵,運行主進程、結束程序
當主進程與進程池進行通信必須使用:
q = multiprocessing.Manager.Queue()
實現多進程版的copy文件夾
import multiprocessing
import os
def copy_file(q,file_name,folder_name,new_name):
f = open(folder_name+"/"+ file_name,"rb")
content = f.read()
f.close()
f1 = open(new_name+"/"+file_name,"wb")
f1.write(content)
f1.close()
# 拷貝完成往隊列裏放入一個信息
q.put(file_name)
def main():
# 獲取用戶要copy的文件夾名稱
folder_name = input("請輸入您要copy文件夾的名稱:")
# 創建一個新的文件夾
try:
new_name = folder_name+"附件"
os.mkdir(new_name)
except:
pass
# 獲取文件夾中所有的待copy的文件名字 os.listdir("路徑")
file_names=os.listdir(folder_name)
# 複製原文件夾中的文件,到新文件夾中去
po = multiprocessing.Pool(3)
# 創建一個隊列q
q = multiprocessing.Manager().Queue()
for file_name in file_names:
po.apply_async(copy_file,args=(q,file_name,folder_name,new_name))
po.close()
#po.join()
# 進程間通信
all_file_name = len(file_names)
copy_num = 0
while True:
file_name = q.get()
print("已經完成copy:{}".format(file_name))
copy_num +=1
print("拷貝進度{}{}".format(copy_num*100/all_file_name,"%"))
if copy_num >=all_file_name:
print("拷貝完成親!!!")
break
if __name__ == '__main__':
main()
迭代器
我們定義一個類Classmate
class Classmate(object):
def __init__(self):
self.names = []
def add(self,name):
self.names.append(name)
# 實例化一下
classmate = Classmate()
# 調用一下add
classmate.add("老外")
classmate.add("張三")
classmate.add("李四")
# 看一下能否迭代
for name in classmate:
print(name) # TypeError: 'Classmate' object is not iterable
那麼我們怎麼能讓一個類可以迭代那?
一個類有__iter__方法叫可迭代
當有__iter__和__next__方法後叫迭代器
每for一次就調用一次__next__返回什麼for出來就是什麼
class Classmate(object):
def __init__(self):
self.names = []
def add(self,name):
self.names.append(name)
self.current_num = 0
def __iter__(self):
"""
如果想要一個對象稱之爲可迭代對象,即可以使用for,
那麼必須實現__iter__方法
"""
return self
def __next__(self):
if self.current_num<len(self.names):
ret = self.names[self.current_num]
self.current_num+=1
return ret
else:
raise StopIteration # 此異常是專門用於迭代器退出的
# 實例化一下
classmate = Classmate()
# 調用一下add
classmate.add("老外")
classmate.add("張三")
classmate.add("李四")
# 看一下能否迭代
for name in classmate:
print(name)
迭代器的使用場景是什麼?會迭代器和不會迭代器有什麼區別?
當有一個很大的列表數據,當我們不會迭代器,就要把整個數據集展示出來,佔用極大的內存
而迭代器,他不是數據集,而是一個可以產生數據集的方式,佔用極小內存。
使用迭代器實現斐伯納耶數列
class Fibonacci(object):
def __init__(self,all_num):
self.all_num = all_num
self.current_num = 0
self.a = 0
self.b = 1
def __iter__(self):
return self
def __next__(self):
lst = []
if self.current_num<self.all_num:
for i in range(self.all_num):
lst.append(self.a)
self.a,self.b = self.b,self.a+self.b
self.current_num+=1
return lst
else:
raise StopIteration
fibo = Fibonacci(10)
for i in fibo:
print(i)
生成器:是迭代器特殊版本
生成器創建方式一、小括號()
# []返回的是一個列表
nums = [x*2 for x in range(10)] # [0,2,4,6,8,12,14,18]
#()返回的是一個生成器,優點:佔用空間小,他產生的不是數據集,而是生成數據集的方法
nums =(x*2 for x in range(10) # <generator object <genexpr> at 0x7f04e12d9690>
生成器創建方式二、函數末尾添加yield就是一個生成器
如果一個函數中yield語句,那麼這個就不是函數,而是一個生成器模板
def create_num(all_num):
a, b = 0,1
current_num =0
while current_num<all_num:
yield a
a, b = b, a+b
current_num+=1
for i in create_num(10):
print(i)
greelet、gevent協程完成多任務
在這裏插入代碼片
圖片下載案例
在這裏插入代碼片