Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add asyncio.Queue __aiter__, __anext__ methods #72963

Closed
RekGRpth mannequin opened this issue Nov 23, 2016 · 9 comments
Closed

Add asyncio.Queue __aiter__, __anext__ methods #72963

RekGRpth mannequin opened this issue Nov 23, 2016 · 9 comments
Labels
3.7 (EOL) end of life topic-asyncio type-feature A feature request or enhancement

Comments

@RekGRpth
Copy link
Mannequin

RekGRpth mannequin commented Nov 23, 2016

BPO 28777
Nosy @gvanrossum, @cjerdonek, @1st1, @RekGRpth

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2017-08-18.20:27:30.503>
created_at = <Date 2016-11-23.04:58:52.383>
labels = ['type-feature', '3.7', 'expert-asyncio']
title = 'Add asyncio.Queue __aiter__, __anext__ methods'
updated_at = <Date 2017-08-18.20:27:30.502>
user = 'https://github.com/RekGRpth'

bugs.python.org fields:

activity = <Date 2017-08-18.20:27:30.502>
actor = 'gvanrossum'
assignee = 'none'
closed = True
closed_date = <Date 2017-08-18.20:27:30.503>
closer = 'gvanrossum'
components = ['asyncio']
creation = <Date 2016-11-23.04:58:52.383>
creator = 'RekGRpth'
dependencies = []
files = []
hgrepos = []
issue_num = 28777
keywords = []
message_count = 9.0
messages = ['281536', '281749', '281750', '299131', '299200', '299688', '299714', '300496', '300530']
nosy_count = 5.0
nosy_names = ['gvanrossum', 'chris.jerdonek', 'yselivanov', 'RekGRpth', 'Matt Rasband']
pr_nums = []
priority = 'normal'
resolution = 'rejected'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue28777'
versions = ['Python 3.7']

@RekGRpth
Copy link
Mannequin Author

RekGRpth mannequin commented Nov 23, 2016

adding to asyncio.Queue class following methods:
def __aiter__(self): return self
async def __anext__(self): return await self.get()
let use asyncio.Queue follow:
queue = asyncio.Queue()
...
async for item in queue: do_something_with(item)

@RekGRpth RekGRpth mannequin added topic-asyncio type-feature A feature request or enhancement labels Nov 23, 2016
@terryjreedy terryjreedy added the 3.7 (EOL) end of life label Nov 25, 2016
@terryjreedy terryjreedy changed the title asinc iter queue Add asyncio.Queue __aiter__, __anext__ methods Nov 25, 2016
@gvanrossum
Copy link
Member

This should be an upstream PR first (GitHub.com/python/asyncio). Also, too late for 3.6.

@gvanrossum
Copy link
Member

Also it's not clear that it's a good idea without more thought -- there's no way to end the loop on the producing side.

@cjerdonek
Copy link
Member

there's no way to end the loop on the producing side.

I might be missing something, but can't something similar be said of queue.get()?

@gvanrossum
Copy link
Member

> there's no way to end the loop on the producing side.

I might be missing something, but can't something similar be said of queue.get()?

That's my point, actually. If you are wrapping the Queue protocol with __aiter__/anext the caller would expect there's a way to signal to the latter that the loop is over (so it can raise StopAsyncIteration). But since .get() doesn't have a way to signal this, an async for-loop would not be able to terminate (other than through break).

@RekGRpth
Copy link
Mannequin Author

RekGRpth mannequin commented Aug 3, 2017

I successfully use my code:

import asyncio, sanic

class MyQueue(asyncio.Queue):
    def __aiter__(self): return self
    async def __anext__(self): return await self.get()

app = sanic.Sanic()
ws_set = set()
app.static('/', 'async.html')

@app.websocket('/ws')
async def root_ws(request, ws):
ws_set.add(ws)
try:
while True: await ws.recv()
finally: ws_set.remove(ws)

async def postgres():
    import aiopg
    async with aiopg.create_pool('') as pool:
        async with pool.acquire() as connection:
            connection._notifies = MyQueue()
            async with connection.cursor() as cursor:
                await cursor.execute('LISTEN message')
                async for message in connection.notifies:
                    for ws in ws_set: await ws.send(message.payload)

try: asyncio.get_event_loop().run_until_complete(asyncio.gather(app.create_server(), postgres()))
except KeyboardInterrupt: asyncio.get_event_loop().stop()

@gvanrossum
Copy link
Member

So that's an infinite loop right?

@MattRasband
Copy link
Mannequin

MattRasband mannequin commented Aug 18, 2017

I attempted this myself, it seemed to have too many costs associated for the stdlib and is something easy enough to wrap myself when I need this functionality with explicit semantics on how to "stop" the queue (using an object() sentinel). My implementation is flawed as the sentinel is global, instead of per queue instance, if you decide to use this at all.

See python/asyncio#445

@gvanrossum
Copy link
Member

Let's not do this.

@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.7 (EOL) end of life topic-asyncio type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants