<bdo id='YmfTm'></bdo><ul id='YmfTm'></ul>

  • <small id='YmfTm'></small><noframes id='YmfTm'>

    1. <i id='YmfTm'><tr id='YmfTm'><dt id='YmfTm'><q id='YmfTm'><span id='YmfTm'><b id='YmfTm'><form id='YmfTm'><ins id='YmfTm'></ins><ul id='YmfTm'></ul><sub id='YmfTm'></sub></form><legend id='YmfTm'></legend><bdo id='YmfTm'><pre id='YmfTm'><center id='YmfTm'></center></pre></bdo></b><th id='YmfTm'></th></span></q></dt></tr></i><div id='YmfTm'><tfoot id='YmfTm'></tfoot><dl id='YmfTm'><fieldset id='YmfTm'></fieldset></dl></div>

      1. <tfoot id='YmfTm'></tfoot>

        <legend id='YmfTm'><style id='YmfTm'><dir id='YmfTm'><q id='YmfTm'></q></dir></style></legend>

        Python从使用线程到使用async/await的深入讲解

        时间:2023-12-16
        <tfoot id='svK59'></tfoot>

            <tbody id='svK59'></tbody>
          <i id='svK59'><tr id='svK59'><dt id='svK59'><q id='svK59'><span id='svK59'><b id='svK59'><form id='svK59'><ins id='svK59'></ins><ul id='svK59'></ul><sub id='svK59'></sub></form><legend id='svK59'></legend><bdo id='svK59'><pre id='svK59'><center id='svK59'></center></pre></bdo></b><th id='svK59'></th></span></q></dt></tr></i><div id='svK59'><tfoot id='svK59'></tfoot><dl id='svK59'><fieldset id='svK59'></fieldset></dl></div>
          <legend id='svK59'><style id='svK59'><dir id='svK59'><q id='svK59'></q></dir></style></legend>

                <small id='svK59'></small><noframes id='svK59'>

                • <bdo id='svK59'></bdo><ul id='svK59'></ul>

                  Python从使用线程到使用async/await的深入讲解

                  1. 线程

                  1.1 什么是线程?

                  线程是程序执行流的最小单元,是进程的一个执行单元。线程通过共享运行时环境,可以提高程序的并发性,线程有轻量级、及时性等特点。

                  1.2 Python的线程模块

                  Python的标准库threading提供了线程相关的模块,使用起来非常简单。

                  import threading
                  
                  def worker():
                      print('Thread %s is working' % threading.current_thread().getName())
                  
                  t = threading.Thread(target=worker)
                  t.start()
                  

                  上述代码中,使用threading.Thread类创建线程对象,使用start方法启动线程,使用current_thread方法获取当前线程对象,使用getName方法获取线程名。

                  1.3 线程的并发问题

                  虽然Python的线程机制非常易用,但是Python的线程是基于操作系统底层线程的,而不是真正的并发线程。因为Python的Global Interpreter Lock (GIL)机制,同一时刻只能有一个线程在执行Python代码,其他线程只能在等待GIL。所以使用线程并不能真正充分利用多核CPU,也无法真正实现多线程并发。因此,使用线程可能带来线程切换的开销而降低程序性能。

                  2. 协程

                  2.1 什么是协程?

                  协程是一种用户态的轻量级线程,也称为纤程 (Fiber),协程可以看作特殊的迭代器,可以由程序员控制运行状态,支持用户态调度,无线程切换开销。

                  2.2 Python的协程模块

                  Python 3.5开始加入async/await语法实现原生协程。使用协程需要用到Python的asyncio模块。

                  下面是一个使用async/await语法的协程示例:

                  import asyncio
                  
                  async def worker():
                      print('Coroutine is working')
                      await asyncio.sleep(1)
                      print('Coroutine is finished')
                  
                  loop = asyncio.get_event_loop()
                  loop.run_until_complete(worker())
                  

                  上述代码中,使用asyncawait定义协程,使用asyncio.sleep模拟协程执行任务,使用get_event_loop方法获取事件循环对象,使用run_until_complete方法运行协程。

                  2.3 协程和线程的区别

                  线程和协程都是并发机制,但是线程是基于操作系统底层线程的,因此他们的并发模型在底层上有很大的区别。协程通过用户态调度,对于大量I/O密集型操作的场景非常适用,但是对于CPU密集型操作的场景则不一定有优势,因为无法利用多核CPU。

                  3. 示例说明

                  3.1 线程示例

                  下面是一个使用线程池的示例,实现并发下载多张图片:

                  import requests
                  import threading
                  from concurrent.futures import ThreadPoolExecutor
                  
                  def download(url, filename):
                      print('Thread %s is downloading image: %s' % (threading.current_thread().getName(), url))
                      resp = requests.get(url)
                      with open(filename, 'wb') as f:
                          f.write(resp.content)
                  
                  urls = ['https://picsum.photos/200/200/?image=%d' % i for i in range(10)]
                  pool = ThreadPoolExecutor(max_workers=5)
                  for i, url in enumerate(urls):
                      filename = 'image_%d.jpg' % i
                      pool.submit(download, url, filename)
                  

                  在该示例中,使用requests发送网络请求下载多张图片,使用ThreadPoolExecutor创建线程池,并通过submit方法向线程池中提交任务。由于线程是基于操作系统底层线程的,所以程序在执行过程中会有线程切换的开销。

                  3.2 协程示例

                  下面是一个使用协程的示例,实现并发下载多张图片:

                  import aiohttp
                  import asyncio
                  
                  async def download(url, filename):
                      print('Coroutine is downloading image: %s' % url)
                      async with aiohttp.ClientSession() as session:
                          async with session.get(url) as resp:
                              with open(filename, 'wb') as f:
                                  f.write(await resp.content.read())
                  
                  urls = ['https://picsum.photos/200/200/?image=%d' % i for i in range(10)]
                  tasks = [download(url, 'image_%d.jpg' % i) for i, url in enumerate(urls)]
                  loop = asyncio.get_event_loop()
                  loop.run_until_complete(asyncio.gather(*tasks))
                  

                  在该示例中,使用aiohttp发送异步网络请求下载多张图片,使用asyncio异步执行协程任务。由于协程是用户态调度,不需要线程切换的开销,可以提高程序的性能。

                  4. 总结

                  线程和协程都是并发编程的重要方式,但是在线程和协程之间需要根据实际需求进行选择。在大量I/O密集型操作的场景下,协程可以取得很好的效果,而在大量CPU密集型操作的场景下,则需要考虑使用多进程或大规模并行计算。

                  上一篇:python脚本实现验证码识别 下一篇:改变 Python 中线程执行顺序的方法

                  相关文章

                  <tfoot id='YJUli'></tfoot>
                • <small id='YJUli'></small><noframes id='YJUli'>

                • <i id='YJUli'><tr id='YJUli'><dt id='YJUli'><q id='YJUli'><span id='YJUli'><b id='YJUli'><form id='YJUli'><ins id='YJUli'></ins><ul id='YJUli'></ul><sub id='YJUli'></sub></form><legend id='YJUli'></legend><bdo id='YJUli'><pre id='YJUli'><center id='YJUli'></center></pre></bdo></b><th id='YJUli'></th></span></q></dt></tr></i><div id='YJUli'><tfoot id='YJUli'></tfoot><dl id='YJUli'><fieldset id='YJUli'></fieldset></dl></div>

                      • <bdo id='YJUli'></bdo><ul id='YJUli'></ul>
                    1. <legend id='YJUli'><style id='YJUli'><dir id='YJUli'><q id='YJUli'></q></dir></style></legend>