python 37 同步、异步调用

目录

  • 1. 阻塞与非阻塞
  • 2. 同步与异步
    • 2.1 异步调用
    • 2.2 同步调用
    • 2.3 异步调用回收的第一种方式
  • 3. 异步调用+回调函数
    • 3.1 requests模块
    • 3.2 异步调用回收的第二种方式

1. 阻塞与非阻塞

执行的角度:

? 阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起(如遇到io操作)。函数只有在得到结果之后才会将阻塞的线程激活。

? 非阻塞:程序没有遇到IO阻塞,或者程序遇到IO,通过某种方式,让CPU强行运行程序。

2. 同步与异步

发布的角度:

? 同步调用:在发出一个任务时,自任务开始运行直到结束(可能遇到IO),只有返回一个返回值之后,才会发出下一个任务。

? 异步调用:一次发布多个任务,然后就直接执行下一行代码。不用等待结束。

shutdown:

  1. 让主进程等待进程池中所有的子进程都结束后,再执行。

    1. 在上一个进程池没有完成所有的任务之前,不允许添加新任务。

一个任务是通过一个函数实现的,任务完成了,它的返回值就是函数的返回值。

2.1 异步调用

# 异步调用
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import time
import random
import os

def task(i):
    print(f'{os.getpid()}开始任务')
    time.sleep(random.randint(1,2))
    print(f'{os.getpid()}任务结束')
    return i

if __name__ == '__main__':
    pool = ProcessPoolExecutor()    # 4个进程
    for i in range(10):
        pool.submit(task, i)
    pool.shutdown(wait=True)
    print("===主")

2.2 同步调用

result() :将异步调用变成同步,必须等到任务完成,返回结果后,再执行下一个。能够接收返回值。

# 同步调用

from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
import time
import random
import os

def task(i):
    print(f'{os.getpid()}开始任务')
    time.sleep(random.randint(1,2))
    print(f'{os.getpid()}任务结束')
    return i

if __name__ == '__main__':
    pool = ProcessPoolExecutor()
    for i in range(10):
        obj = pool.submit(task, i)  # 动态对象,能够返回当前对象的状态, running、peeding、finishhed三种状态。
        print(f'任务结果:{obj.result()}')   # 将返回的结果打印
    pool.shutdown(wait=True)
    print("===主")

2.3 异步调用回收的第一种方式

统一回收结果,不能够马上接收任何一个返回值(实时)。

# 异步调用 接收返回值的第一种方式:
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time
import random
import os

def task(i):
    print(f'{os.getpid()}开始任务')
    time.sleep(random.randint(1,3))
    print(f'{os.getpid()}任务结束')
    return i

if __name__ == '__main__':

    # 异步调用
    pool = ProcessPoolExecutor()    # 4个进程
    l1 = []
    for i in range(10):
        obj = pool.submit(task,i)
        l1.append(obj)      # 将对象放入容器中。

    pool.shutdown(wait=True)
    print(l1)
    for i in l1:
        print(i.result())
    print('===主')

3. 异步调用+回调函数

3.1 requests模块

? 浏览器原理:向服务端发送一个请求,服务端验证,如果是正确的,会返回一个文件;浏览器接收到文件,将文件里面的代码渲染后展示到屏幕上。

爬虫:

? 1.利用代码模拟浏览器发送伪装的请求,会得到一堆源代码;

? 2.对源代码进行数据清洗得到想要的数据。

3.2 异步调用回收的第二种方式

要求:

  1. 要做到实时回收结果,第一种方式没有实时。
  2. 并发执行任务,只是用来处理IO阻塞的(爬虫也是阻塞),不能增加新的功能(清洗数据功能),否则容易造成耦合。

解决:增加回调函数。

回调函数:按顺序接收每个任务的结果,进行下一步的数据处理。 对象. add_done_callback(方法名)

异步处理IO类型,回调函数处理非IO,才可用异步 + 调用。

线程 + 回调:将处理的数据交给空闲的线程去执行;

进程 + 回调:将处理的数据交给主进程去执行。

from concurrent.futurse import ThreadPoolExecutor
import requests

def task(url):
    """模拟爬取多个源代码,有IO操作"""
    response = requests.get(url)
    if response.status_code == 200:
        return response.text

def parse(obj):
    """模拟对数据进行分析,一般没有IO"""
    print(len(obj.result()))

if __name__ == '__main__':
    url_list = [
        'http://www.baidu.com',
        'http://www.JD.com',
        'http://www.JD.com',
        'http://www.JD.com',
        'http://www.taobao.com',
        'https://www.cnblogs.com/jin-xin/articles/7459977.html',
        'https://www.cnblogs.com/yzm1017/',
        'https://www.cnblogs.com/jin-xin/articles/9811379.html',
        'https://www.cnblogs.com/jin-xin/articles/11245654.html',
        'https://www.sina.com.cn/']
    pool = ThreadPoolExecutor(4)    # 4个线程
    for url in url_list:
        obj = pool.submit(task, url)
        obj.add_done_callback(parse)        # 回调函数
    """
    线程池设置4个线程, 异步发起10个任务,每个任务是通过网页获取源码, 并发执行,
    当一个任务完成之后,将parse这个分析代码的任务交由剩余的空闲的线程去执行,你这个线程继续去处理其他任务。
    """
"""
2381
99306
99306
2708
21634
47067
99306
143930
571258
48110
"""

原文地址:https://www.cnblogs.com/yzm1017/p/11419946.html

时间: 2024-11-10 20:04:50

python 37 同步、异步调用的相关文章

同步异步调用的一些小问题

随着项目第一次真正接触.使用了同步和异步.记录一下有一些个人的赶脚: .NET现在提供了一个很方便的功能: async, await. 1. 标识为了async的方法便是异步方法,该类方法的返回值只能是void或者Task<T>.(如:Task<bool> PingAsync();) 2. 当需要获得该异步方法的返回值的时候,在调用处必须要用await来标明:可以理解为等待这个异步方法的返回值.(如:var result = await _serverFacade.PingAsyn

pythonのgevent同步异步区别

1 #!/usr/bin/env python 2 3 from urllib import request 4 import gevent 5 from gevent import monkey 6 import time 7 8 monkey.patch_all() # 把当前程序所有的IO操作给我单独的做上标记. 9 def f(url): 10 resp = request.urlopen(url) 11 data = resp.read() 12 print(len(data)) 13

# 进程/线程/协程 # IO:同步/异步/阻塞/非阻塞 # greenlet gevent # 事件驱动与异步IO # Select\Poll\Epoll异步IO 以及selectors模块 # Python队列/RabbitMQ队列

1 # 进程/线程/协程 2 # IO:同步/异步/阻塞/非阻塞 3 # greenlet gevent 4 # 事件驱动与异步IO 5 # Select\Poll\Epoll异步IO 以及selectors模块 6 # Python队列/RabbitMQ队列 7 8 ############################################################################################## 9 1.什么是进程?进程和程序之间有什么

C#:Func的同步、异步调用(转)

实际开发中,对于一些耗时较长的操作,我们往往会将其封装成异步方式调用,以加速系统响应或改善用户体验,下面是一个示例: 有一个现成的类MyMath,里面有一个Add方法: 1 public class MyMath 2 { 3 4 public int Add(int a, int b) 5 { 6 System.Threading.Thread.Sleep(5000); 7 return a + b; 8 } 9 10 } 对Add方法做下封装,对了对比,同时提供“同步调用”与"异步调用&quo

Python并发编程之同步\异步and阻塞\非阻塞

一.什么是进程 进程: 正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 进程和程序的区别: 程序仅仅只是一堆代码而已,而进程指的是程序的运行过程. 需要强调的是:同一个程序执行两次,那也是两个进程,比如打开暴风影音,虽然都是同一个软件,但是一个可以播郭德纲,一个可以播高晓松. 二.并行和并发 无论是并行还是并发,在用户看来都是'同时'运行的,不管是进程还是线程,都只是一个任务而已,真是干活的是cpu,cpu来做这些任务,而一个cpu同一时刻只能执行一个任务 (一)并发:是伪并行,即

python第三十七天,GIL全局解释器锁*****,线程池与进程池 同步异步,阻塞与非阻塞,异步回调

GIL全局解释器锁 1.什么是GIL 官方解释:'''In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe

python37 1.GIL--全局解释器锁 2.GIL带来的问题 3.为什么需要GIL 4.GIL的加锁解锁时机 5.关于GIL的性能的讨论 6.线程常用方法 7.GIL锁与自定义锁的区别 8.进程池与线程池 9.同步异步 10.异步调用

复习1.JoinableQueue--可以被join的队列2.多线程3线程的使用方法与进程一模一样3.1守护线程3.2线程安全问题3.3解决方案3.3.1互斥锁mutex3.3.2递归锁Rlock3.3.3信号量semaphore3.3.4死锁问题 详解:1.JoinableQueue--可以被join的队列 1.1join是等待任务结束 队列怎么叫结束 调用task_done一次则表示有一个数据被处理完成了,当task_done次数等于put的次数就意味着任务处理完成了 1.2这就是join的

python 之 并发编程(进程池与线程池、同步异步阻塞非阻塞、线程queue)

9.11 进程池与线程池 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务 池子内什么时候装进程:并发的任务属于计算密集型 池子内什么时候装线程:并发的任务属于IO密集型 进程池: from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor import time,os,random ? def task(x): print('%s 接客' %os.getpid()) time.

同步调用和异步调用同时存在导致的混乱

其实在Promise之外也存在这个问题,这里我们以一般的使用情况来考虑此问题.这个问题的本质是接收回调函数的函数,会根据具体的执行情况,可以选择是以同步还是异步的方式对回调函数进行调用.下面我们以 onReady(fn) 为例进行说明,这个函数会接收一个回调函数进行处理. mixed-onready.js function onReady(fn) { var readyState = document.readyState; if (readyState == 'interactive' ||