python基礎-Thread基本使用,查看線程數,鎖,進程實現多任務,通過Queue隊列進程間通信,進程池Pool,迭代器,生成器,yield協程完成多任務,圖片下載案例

簡答來一個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協程完成多任務

在這裏插入代碼片

圖片下載案例

在這裏插入代碼片
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章