目录
线程与进程
-
线程
线程模块
线程模块提供了Thread类来处理线程,Thread类提供了以下方法:
- run(): 用以表示线程活动的方法。
- start():启动线程活动。
- join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
- isAlive(): 返回线程是否活动的。
- getName(): 返回线程名。
- setName(): 设置线程名。
使用 threading 模块创建线程的方法
第一种方法:
from threading import Thread
if __name__==__main__:
a = Thread(target = func, args = (1,))
a.start()
第二种方法:
class mythread(Thread):
def __init__(self):
xxx
def run(self): 固定格式
xxx
a = mythread()
a.start()
线程同步
锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续
threadLock = threading.Lock()
# 获取锁,用于线程同步
threadLock.acquire()
# 释放锁,开启下一个线程
threadLock.release()
线程优先级队列( Queue)
Python 的 Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列 PriorityQueue。
这些队列都实现了锁原语,能够在多线程中直接使用,可以使用队列来实现线程间的同步。
Queue 模块中的常用方法:
- Queue.qsize() 返回队列的大小
- Queue.empty() 如果队列为空,返回True,反之False
- Queue.full() 如果队列满了,返回True,反之False
- Queue.full 与 maxsize 大小对应
- Queue.get([block[, timeout]])获取队列,timeout等待时间
- Queue.get_nowait() 相当Queue.get(False)
- Queue.put(item) 写入队列,timeout等待时间
- Queue.put_nowait(item) 相当Queue.put(item, False)
- Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
- Queue.join() 实际上意味着等到队列为空,再执行别的操作
-
进程
from multiprocessing import Process
与线程类似
-
线程池,进程池
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
with ThreadPoolExecutor(20) as t:
for i in range(1000):
t.submit(target = xx, args = (xxx,))
print(“ok”)
-
协程
概念理解
在单线程下,当前任务中有些操作会使线程处于阻塞状态(如:time.sleep(),requests.get(),fp.read()等,IO操作),此时CPU不会为其工作。
为了提高效率,使用多任务异步协程,即让CPU在当前任务处于阻塞状态时切换到其他任务下进行工作。
多任务异步协程
async/await 关键字:用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。
1.协程遇到await,事件循环就会挂起这个协程,执行别协程,直到其他协程也挂起或执行完毕,在进行下一个协程的执行。
2.如果一个对象可以在 await 语句中使用,那么它就是 可等待 对象。可等待 对象有三种主要类型: 协程, 任务 和 Future 。
协程对象:通过调用async特殊函数返回协程对象
任务对象:高级的协程对象,是对协程对象的进一步封装。可以给任务对象绑定 回调(普通函数)
1.创建:task = asyncio.ensure_future(func) ensure_future 也接受任何等待的对象
task = asyncio.creat_task(func) create_task 只接受协程
2.绑定回调函数:task.add_done_callback(func)
事件循环对象:若开启,则其内部装载的任务对象表示的指定操作会被异步执行
1.创建:loop = asyncio.get_event_loop()
2.装载并启动:loop.run_until_complete(task)
例子:
import asyncio
async def func():
print("等待两秒")
await asyncio.sleep(2)
print("hello,world!")
async def func2():
print("等待一秒")
await asyncio.sleep(1)
print("hello,boy!")
async def main():
tasks = [asyncio.creat_task(func()), asyncio.creat_task(func2())]
await async.wait(tasks)
if __name__ == "__main__":
asyncio.run(main())
异步http请求
基本语法
async with aiohttp.request('GET','https://github.com') as r:
await r.text()
或:
async with aiohttp.ClientSession() as session:
async with session.get('https://github.com', timeout=60) as r:
await r.text()
其中r.text(), 可以在括号中指定解码方式:
await r.text(encoding='windows-1251')
或者也可以选择不编码,适合读取图像等,是无法编码的:
await r.read()
或者选择json格式:
await r.json(encoding = "utf-8")
字节流
一般地,我们应该使用以下的模式来把读取的字节流保存到文件中:
with open(filename, 'wb') as fd:
while True:
chunk = await resp.content.read(chunk_size)
if not chunk:
break
fd.write(chunk)