python高阶编程(1)

GIL全局解释锁

  • GIL与python语言没有关系,仅仅由于历史原因在Cpython虚拟机(解释器)中难以移除
  • 每个线程在执行的过程中都要先获取GIL,保证同一时刻只有一个线程可以执行代码
  • 线程释放GIL:在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL
  • Python可以使用多进程来利用多核的CPU资源
  • 多线程在网络编程中比单线程性能有提升,因为碰到IO阻塞会自动释放GIL锁(发送请求的等待响应时立马发送下一个请求)

计算密集型使用CUP用进程,IO密集型用线程、协程,线程和协程只有一个CPU在计算

深拷贝、浅拷贝

Python中的深拷贝会复制对象本身并新建一个对象,浅拷贝则只是在原本的对象中加了一个新的引用。

浅拷贝

a = [1,2]
b = a  #将b指向列表,并没有新建一个[1,2]列表,C语言会新建一个一样的列表,即在python中a,b的地址一样

深拷贝

import copy
a = [1,2]
b = copy.deepcopy(a) #新建一个[1,2]的列表,ab的地址不同

python 并发

引入并发,是为了提升程序运行速度

python 并发编程的三种方式

CPU密集型和IO密集型

多线程、多进程、多协程

多线程

1、准备一个函数

def my_func(a,b):
    do_something(a,b)

2、多线程

import threading
t = threading.Thread(target=my_func,args=(100,200,)) #创建一个线程
t.start() #启动线程
t.join()  #等待结束

实例

def multi_thread():
    threads = []
    for i in range(5):
        threads.append(
        threading.Tread(target=my_func,args=(100,200,)))
    for thread in threads:
        thread.start()
    for thread in threads:
        thread.join()

lock解决线程安全问题

线程池

使用进程池的好处

TreadPoolExecutor

from concurrent.futures import TreadPoolExecutor,as_completed

map函数

with ThreadPoolExecutor()as pool:
    results = pool.map(my_func,urls) #my_func为执行函数名,urls为参数列表
    for result in results:
        print(result)

future模式 更强大

with ThreadPoolExecutor()as pool:
    futures = [pool.submit(my_func,url)for url in urls]
    for future in futures:
        print(future.result()) #等待执行结果进行返回
    for future in as_completed(futures): #使用as_completed顺序不固定
        print(future.result())  #先执行完的先返回

多进程

协程

python异步IO库介绍:asyncio

import asyncio

#获取事件循环
loop = asyncio.get_event_loop()
#定义协程
async def my_func(url):
    await get_url(url) #io走到这里不进行阻塞(等待)而是获取下一个事件循环
#创建task列表
tasks = [loop.create_task(my_func(url))for url in urls]  #对应第一行代码
#执行事件列表
loop.run_until_complete(asyncio.wait(tasks))

注:requests库不支持异步,要使用aiohttp实现

aiohttp

import aiohttp
import asyncio
async def main():
    # 创建aiohttp会话处理请求
    async with aiohttp.ClientSession() as session:
        tasks = [] # 要执行的任务
        for url in urls:
            task = asyncio.ensure_future(download(session, url)) # 需要异步执行的函数,不用等结果返回
            tasks.append(task)
        result = await asyncio.gather(*tasks) # 获取tasks内容,*tasks表示task1 task2 ...., result是一个保存所有任务执行download()后返回的数据的列表,

async def download(session, url):
    async with session.get(url) as response:
        result_data = await response.json()
        return result_data

# 运行异步函数需要使用循环
asyncio.run(main())  # 创造循环

   转载规则


《python高阶编程(1)》 fightingtree 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录