Coroutine in python between 3.4 and 3.5, How can I keep backwords compatibility?

前端 未结 1 1225
无人及你
无人及你 2021-02-05 22:05

I\'m on developing python chatting bot framework with asyncio. But I watch PEP-492 and there is new syntax, async/await and finally it acc

相关标签:
1条回答
  • 2021-02-05 22:16

    If you need to support Python 3.4 in your code, you'll need to use the old @asyncio.coroutine/yield from style syntax. There's no way to support the async/await syntax without running 3.5; you'll get a SyntaxError at compilation time on 3.4 or lower.

    The only thing that takes advantage of the new features you can do in a backwards-compatible way is add the various __a*__ methods to your classes where appropriate (__aiter__, __aenter__, __aexit__, etc.), using the yield from coroutine syntax. That way, your objects can support async with/async for statements, so that users of your library running Python 3.5 could take advantage of the new features.

    For example, this class can be used with async with, but won't break when run on Python 3.4:

    import asyncio
    
    class Test:
        def __enter__(self):
            return self
    
        def __exit__(self, *args):
            print("arg")
    
        @asyncio.coroutine
        def __aenter__(self):
            yield from self.init_state()
            return self
    
        @asyncio.coroutine
        def init_state(self):
            yield from asyncio.sleep(2) # Pretend this is real initialization
    
        @asyncio.coroutine
        def __aexit__(self, *args):
            return self.__exit__(self, *args)
    

    On Python 3.5:

    import asyncio
    from test import Test
    
    async def main():
        print("entering with")
        async with Test() as t:
            print("in here")
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    

    On Python 3.4

    import asyncio
    from test import Test
    
    @asyncio.coroutine
    def oldmain():
        print("entering with")
        with Test() as t:
            yield from t.init_state()
            print("in here")
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(oldmain())
    

    This probably isn't useful if you're writing an application that uses asyncio, but if you're developing a library or framework intended to be used by other developers, it's worth doing.

    0 讨论(0)
提交回复
热议问题