Pythonの並行プログラミング(8)同期および非同期実装

同期および非同期実装

  1. 3つの状態が実行されました:ランニング、準備が、ブロックされました

  2. ブロッキング、ノンブロッキング、同期、非同期

    • (角度ランニング)をブロッキング:ランニング、IO、プログラムがハングに遭遇し、CPUが切り取ら
    • (角度ランニング)ノンブロッキング:プログラムは、IOに遭遇しませんでした。私はIOに遭遇しましたが、いくつかの手段によって、CPUが私のプログラムを実行するように強制しましょう
    • 同期(角度がタスクを提出):先生が最初の最初のタスクが本を書い完了したことを告げた:私は(例次のタスクを提出した後、タスクを提出、タスクは、戻り値を返す(IOがあるかもしれない)タスクの終了までから実行し始めました私は場所を待つ、と彼は二日後に完了し、私は次のタスクを公開する、逃げるように言わ...)
    • 非同期(角度がタスクを提出):一度に複数のタスクを提出した後、私は、コードの次の行を実行します(例:直接は私私の忙しい私に教えてくれ3人の教師が終了するまで、3つのタスクの先生を通知します)
      • 戻る非同期回復の結果?
  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()
          for i in range(10):
              pool.submit(task,i)
      
          pool.shutdown(wait=True)
          #shutdown:让我的主进程等待进程池中所有的子进程都结束任务之后,再执行,有点类似与join
          #shutdown:在上一个进程池没有完成所有的任务之前,不允许添加新的任务
          #一个任务时通过一个函数实现的,任务完成得返回值就是函数得返回值
          print('====主')
    • 同期呼び出し:

      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()
          for i in range(10):
              obj=pool.submit(task,i)
              #obj是一个动态对象,返回当前的而对象状态,有可能运行中,有可能(就绪,堵塞)还有可能是结束了
              obj.result()#必须等到这个任务完成后,返回了结果之后,在执行下一个任务
              print(f'任务结果{obj.result()}')
      
          pool.shutdown(wait=True)
          #shutdown:让我的主进程等待进程池中所有的子进程都结束任务之后,在执行,有点类似join
          #shutdown:在上一个进程池没有完成所有的任务之前,不允许添加新的任务
          #一个任务是通过一个函数实现的,任务完成了,他的返回就是函数的返回值
          print('====主')
  4. どのように非同期の結果を得ますか?

    • 最初の方法:制服リサイクル結果

      • 方式一:异步调用,统一回收结果
        
        from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
        import time
        import os
        import random
        
        def task(i):
            print(f'{os.getpid()}任务开始')
            time.sleep(random.randint(1,3))
            print(f'{os.getpid()}任务结束')
            return i
        
        if __name__ == '__main__':
            l1=[]
            pool=ProcessPoolExecutor()
            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('全')
        
            #统一回收结果:我不能马上收到任何一个已经完成任务的返回值,我只能等到所有任务结束统一回收
    • 第二の方法:1つの回復ずつ

      import requests
      
      def task(url):
          """模拟的就是爬取多个源代码,一定有IO操作"""
          ret=requests.get(url)
          if ret.status_code==200:
              return ret.text
      
      def parse(content):
          """模拟对数据进行分析 一般没有IO 如果都有IO用回调函数就没有意义"""
          return len(content)
      if __name__ == '__main__':
          """串行,耗费时间长"""
          ret=task('http://www.baidu.com')
          print(parse(ret))
          ret = task('http://www.JD.com')
          print(parse(ret))
  5. 非同期コールバックコール+

    • ブラウザが動作します:正しい場合は、お使いのブラウザを与え、あなたの要求を確認するために、サーバー、サーバーに要求を送信あなたが見る、コード内のファイルはかなり美しいレンダリングされ、ブラウザがファイルを受信し、ファイルを返します。外観

    • 何爬虫類?

      1. コードを使用してブラウザをシミュレートし、ブラウザは、ソースコードの束のためのワークフローを実行します
      2. データクレンジングのためのソースコードは、私が欲しいデータを取得します
    • モジュールリクエストの内部に取り付けられ第3のモジュールにPIPモジュール、

      • アナログブラウザ

        import requests#导入requests模块
        ret=request.get('http://www.baidu.com')#
        if ret.status_code==200:#如果请求状态是成功
         print(ret.text)#则把源码打印出来
    • 非同期呼び出し+コールバック関数(バージョン)

      from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
      import time
      import random
      import os
      import requests
      
      def task(url):
          """模拟的就是爬去多个源代码 一定有IO操作"""
          ret=requests.get(url)
          if ret.status_code==200:
              return ret.text
      
      def parse(content):
          """模拟对数据进行分析 一般没有IO 如果有IO 会回调函数就没有意义"""
          return len(content)
      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.luffycity.com/',
              '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)
          obj_list=[]
          for url in url_list:
              obj=pool.submit(task,url)
              obj_list.append(obj)
          pool.shutdown(wait=True)
          for res in obj_list:
              print(parse(res.result()))
          print("===主")
      #版本一:
      #1.异步发出10个任务,并发的执行,但是统一的接受所有的任务返回值(效率低,不能实时的获取结果)
      #2.分析结果流程是串行,影响效率
      #for res in obj_list:
      #   print(parse(res.result()))
    • 非同期呼び出し+コールバック関数(第二版)

      #版本二:针对版本一的缺点2,让串行变成并发或者并行
      from concurrent.futures import  ProcessPoolExecutor,ThreadPoolExecutor
      import time
      import random
      import os
      import requests
      
      def task(url):
          """模拟的就是爬取多个源代码 一定有IO操作"""
          ret=requests.get(url)
          if ret.status_code==200:
              return parse(ret.text)
      def parse(content):
          return len(content)
      
      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.luffycity.com/',
                  'https://www.cnblogs.com/jin-xin/articles/9811379.html',
                  'https://www.cnblogs.com/jin-xin/articles/11245654.html',
                  'https://www.sina.com.cn/',
      
              ]
          pool=ProcessPoolExecutor(4)
          obj_list=[]
          for url in url_list:
              obj=pool.submit(task,url)
              obj_list.append(obj)
          '''
          # 1 在开一个线程进程池,并发并行的处理. 再开一个线程进程池,开销大.
          # 2 将原来的任务扩大,
          版本一:
              线程池设置4个线程, 异步发起10个任务,每个任务是通过网页获取源码, 并发执行,
              最后统一用列表回收10个任务, 串行着分析源码.
          版本二:
              线程池设置4个线程, 异步发起10个任务,每个任务是通过网页获取源码+数据分析, 并发执行,
              最后将所有的结果展示出来.
              耦合性增强了.
              并发执行任务,此任务最好是IO阻塞,才能发挥最大的效果
          '''
          pool.shutdown(wait=True)
          for res in obj_list:
              print(res.result())
    • 非同期呼び出し+コールバック関数(第3版)

      • #版本三:
        #基于异步调用回收所有任务结果我要做实时回收结果
        #并发执行任务每个任务只是处理IO阻塞,不能增加新功能
        from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
        import time
        import random
        import os
        import requests
        
        def task(url):
            """模拟就是爬去多个源代码 一定有IO操作"""
            ret=requests.get(url)
            if ret.status_code==200:
                return ret.text
        
        def parse(obj):
            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.luffycity.com/',
                '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)
            for url in url_list:
                obj=pool.submit(task,url)
                obj.add_done_callback(parse)
                """
                线程池设置4个线程,异步发起10个任务,每个任务都是通过网页获取源码,并发执行
                当一个任务完成之后,将parse这个分析代码的任务交由剩余的空闲的线程去执行,你这个线程继续处理其他任务
                如果进程池+回调:回调函数由主进程去执行
                如果线程池+回调:回调函数由空闲线程去执行
                """
    • そして、非同期コールバックの違いは?

      • 非同期パブリッシングタスクの視点に立っています
      • コールバック:、各タスクの結果を受け入れるために、次のステップをコールバック関数:立って角度の結果を受け入れます
      • 非IO IOタイプのコールバックハンドラタイプの非同期処理

おすすめ

転載: www.cnblogs.com/zhangdadayou/p/11432097.html