爬虫基础(笔记)——3.线程与进程

目录

线程与进程

线程

线程模块

使用 threading 模块创建线程的方法

线程同步

线程优先级队列( Queue)

进程

线程池,进程池

 协程

概念理解

多任务异步协程

异步http请求

 字节流


线程与进程

  • 线程

线程模块

线程模块提供了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)

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值