classification
Title: Proposial add loop parametr to run in asyncio
Type: Stage: resolved
Components: asyncio Versions: Python 3.9
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: asvetlov, cjrh, heckad, yselivanov
Priority: normal Keywords: patch

Created on 2020-01-29 11:52 by heckad, last changed 2020-02-12 00:05 by yselivanov. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 18248 closed heckad, 2020-01-29 12:03
Messages (11)
msg360957 - (view) Author: Андрей Казанцев (heckad) * Date: 2020-01-29 11:52
Sometimes need get loop from another place and run corutine in it. For example when use teleton lib. Example from this lib https://docs.telethon.dev/en/latest/basic/signing-in.html#id2 suggests using ```client.loop.run_until_complete``` but it's not handle errors like in run method.
msg360959 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2020-01-29 13:13
-1.
I rather suggest updating telethon example in the following matter:

async with main():
    with TelegramClient('anon', api_id, api_hash) as client:
        await client.send_message('me', 'Hello, myself!')

You PR brings more problems than fixes: the loop is closed after the first usage, the next call with the same loop fails.
I don't think that we should support such tricky mode.
msg360960 - (view) Author: Андрей Казанцев (heckad) * Date: 2020-01-29 13:38
I create the client object in `bot` file. If I import it then it creates loop when will import and then when I run it I will get errors attaching to a different loop. Another way to use `import` statement in main. This is blocking code. What to choose?
msg360962 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2020-01-29 14:07
A client that creates a loop implicitly in the constructor is a weird design from my perspective.

You are free to use it, sure -- but please let us keep the freedom to not support such corner cases by asyncio.run()

Sorry, I don't know the telethon library good enough to suggest the best workaround.
msg360983 - (view) Author: Андрей Казанцев (heckad) * Date: 2020-01-29 19:49
How to make singleton class? I wrote this 

```
import asyncio


class Singleton:
    _CREATE_LOCK = asyncio.Lock()

    @classmethod
    async def create(cls):
        if not hasattr(cls, '_Singleton__instance'):
            async with cls._CREATE_LOCK:
                if not hasattr(cls, '_Singleton__instance'):
                    await asyncio.sleep(1)
                    cls.__instance = cls()
        return cls.__instance


async def main():
    await asyncio.wait([
        Singleton.create(),
        Singleton.create(),
    ])


if __name__ == '__main__':
    asyncio.run(main())
```

and got `RuntimeError`
msg361077 - (view) Author: Андрей Казанцев (heckad) * Date: 2020-01-30 19:44
@asvetlov, I provided an example where else this useful feature would be. What do you think?
msg361096 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2020-01-31 09:44
Explicit error is better than error-prone design.
Think that we will deprecate asyncio.get_event_loop() and the loop instantiation on-demand in the main thread.
msg361100 - (view) Author: Андрей Казанцев (heckad) * Date: 2020-01-31 11:08
Where can I find issue which you are discussing for this thread?
msg361206 - (view) Author: Caleb Hattingh (cjrh) * Date: 2020-02-02 04:30
@heckad You should instead ask the maintainers of teleton how to use their library with asyncio.run, not the other way round.
msg361207 - (view) Author: Caleb Hattingh (cjrh) * Date: 2020-02-02 04:35
Hmm, my recent comment looks rude but I didn't intend it to be that way. What I mean is: there are many, many more users of asyncio.run than there are of teleton, so any change made to asyncio.run is going to affect more people than the other way round. So before we regard this as something that will be generally useful (run() taking a loop parameter), it will be faster to check if the 3rd party library provides a way to work with the std library.  FWIW I have an alternative run() implementation, with the PYPI package "aiorun" in which I do allow a loop parameter to be passed in. So far, it's only caused headaches for me as the maintainer :)
msg361841 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2020-02-12 00:05
Андрей,

Here's how you can fix your example:


import asyncio


class Singleton:
    _LOCK = None
    _LOOP = None

    @classmethod
    async def create(cls):
        if cls._LOOP is None:
            cls._LOOP = asyncio.get_running_loop()
            cls._LOCK = asyncio.Lock()
        loop = cls._LOOP
        if loop is not asyncio.get_running_loop():
            raise RuntimeError()

        if not hasattr(cls, '_Singleton__instance'):
            async with cls._LOCK:
                if not hasattr(cls, '_Singleton__instance'):
                    await asyncio.sleep(1)
                    cls.__instance = cls()
        return cls.__instance
History
Date User Action Args
2020-02-12 00:05:07yselivanovsetmessages: + msg361841
2020-02-02 10:57:13asvetlovsetstatus: open -> closed
resolution: wont fix
2020-02-02 04:35:04cjrhsetmessages: + msg361207
2020-02-02 04:30:07cjrhsetnosy: + cjrh
messages: + msg361206
2020-01-31 11:08:44heckadsetstatus: closed -> open
resolution: rejected -> (no value)
messages: + msg361100
2020-01-31 09:44:32asvetlovsetstatus: open -> closed
resolution: rejected
messages: + msg361096

stage: patch review -> resolved
2020-01-30 19:44:45heckadsetmessages: + msg361077
2020-01-29 19:49:18heckadsetmessages: + msg360983
2020-01-29 14:07:07asvetlovsetmessages: + msg360962
2020-01-29 13:38:46heckadsetmessages: + msg360960
2020-01-29 13:13:46asvetlovsetmessages: + msg360959
2020-01-29 12:03:19heckadsetkeywords: + patch
stage: patch review
pull_requests: + pull_request17627
2020-01-29 11:52:27heckadcreate