3

I often see code like along the lines of the following (which is similar to examples in aiohttp docs).

@asyncio.coroutine
def init(loop):
    srv = yield from loop.create_server(web.Application().make_handler(), '0.0.0.0', 8080)
    return srv

Are there any advantages/disadvantages to doing it in 1 line as below, presuming you don't want to do anything to the srv object in between getting it and returning it?

@asyncio.coroutine
def init(loop):
    return (yield from loop.create_server(web.Application().make_handler(), '0.0.0.0', 8080))
neRok
  • 995
  • 9
  • 21
  • 1
    Am I missing something, or is this equivalent to `return loop.create_server(web.Application().make_handler(), '0.0.0.0', 8080)`? The examples I see in the aiohttp docs only do anything like `return (yield from whatever)` when they need to perform other yields in the same function. – user2357112 Jul 09 '15 at 04:58
  • 2
    A very practical difference (which however is very minor here) is that with fewer function calls per source line, the traceback you get in case of an error will be more helpful when you see exactly which function call is failing. – tripleee Jul 09 '15 at 04:59
  • @user2357112, there may or may not be more other yields in the function, but I don't think it would make a difference. Really I am asking if you should yield to a variable, then return the variable, OR directly return the yield. – neRok Jul 09 '15 at 05:08
  • @tripleee, yes I suppose tracebacks would look a bit nicer. Also, putting the object in a variable kind of documents what the object is, and makes it a bit more obvious what you are returning. – neRok Jul 09 '15 at 05:10

1 Answers1

6

The example in the aiohttp docs you seem to have adapted has important additional code:

@asyncio.coroutine
def init(loop):
    app = web.Application(loop=loop)
    app.router.add_route('GET', '/{name}', handle)

    srv = yield from loop.create_server(app.make_handler(),
                                        '127.0.0.1', 8080)
    print("Server started at http://127.0.0.1:8080")  # THIS PART
    return srv

The function needs to do something between the yield from and the return, so it needs to save the return value to a variable. If there is no need to do something between the yield and the return, it is indeed equivalent to do

return (yield from whatever)

instead of

srv = yield from whatever
return srv

and you can see that done in other examples on the same page:

@asyncio.coroutine
def fetch_page(url):
    response = yield from aiohttp.request('GET', url)
    assert response.status == 200
    return (yield from response.read())

For an example as simple as your code, I don't think you even need the yield from. You should be able to do

@asyncio.coroutine
def init(loop):
    return loop.create_server(web.Application().make_handler(), '0.0.0.0', 8080)

though I'm not familiar with asyncio, so I'm not entirely sure that that won't interact weirdly with the asyncio.coroutine decorator.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • "If there is no need to do something between the yield and the return, it is indeed equivalent" - that's the bit I was curious about. The code I used in my example was probably a poor choice. – neRok Jul 09 '15 at 05:14