“async with” in Python 3.4

前端 未结 2 901
时光取名叫无心
时光取名叫无心 2021-02-05 04:36

The Getting Started docs for aiohttp give the following client example:

import asyncio
import aiohttp

async def fetch_page(session, url):
    with aiohttp.Timeo         


        
2条回答
  •  灰色年华
    2021-02-05 05:05

    aiohttp's examples implemented using 3.4 syntax. Based on json client example your function would be:

    @asyncio.coroutine
    def fetch(session, url):
        with aiohttp.Timeout(10):
            resp = yield from session.get(url)
            try:
                return (yield from resp.text())
            finally:
                yield from resp.release()
    

    Upd:

    Note that Martijn's solution would work for simple cases, but may lead to unwanted behavior in specific cases:

    @asyncio.coroutine
    def fetch(session, url):
        with aiohttp.Timeout(5):
            response = yield from session.get(url)
    
            # Any actions that may lead to error:
            1/0
    
            return (yield from response.text())
    
    # exception + warning "Unclosed response"
    

    Besides exception you'll get also warning "Unclosed response". This may lead to connections leak in complex app. You will avoid this problem if you'll manually call resp.release()/resp.close():

    @asyncio.coroutine
    def fetch(session, url):
        with aiohttp.Timeout(5):
            resp = yield from session.get(url)
            try:
    
                # Any actions that may lead to error:
                1/0
    
                return (yield from resp.text())
            except Exception as e:
                # .close() on exception.
                resp.close()
                raise e
            finally:
                # .release() otherwise to return connection into free connection pool.
                # It's ok to release closed response:
                # https://github.com/KeepSafe/aiohttp/blob/master/aiohttp/client_reqrep.py#L664
                yield from resp.release()
    
    # exception only
    

    I think it's better to follow official examples (and __aexit__ implementation) and call resp.release()/resp.close() explicitly.

提交回复
热议问题