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 accepted.
I like async/await syntax and I want to use it. but I worry about 3.4 backwords compatibility.
If I use new syntax in my code, someone can use it in 3.4?
For example, I write some code like this,
import asyncio
class ChatBot:
def __init__(self, loop):
self.loop = loop
async def connect(self):
self.reader, self.writer = await asyncio.open_connect(HOST, PORT, loop=self.loop)
async def read():
return await self.reader.read()
async def run(self):
running = True
while running:
try:
await self.connect()
line = await self.read()
if not line:
continue
await self.parse(line)
except BotInternalError as e:
if e.stop:
running = False
break
except:
pass
async def parse(self, msg):
if msg.startswith('PING'):
self.pong()
elif msg.startswith('ERROR'):
self.error()
else:
await self.some_work(msg)
async def some_work(self, msg):
# some looooooooong works
self.send(msg)
def send(self, msg):
self.writer.write(msg)
Than, I can use it with this source in py35
loop = asyncio.get_event_loop() # I don't know it really needed in py35.
bot = ChatBot(loop)
asyncio.run_until_complete(bot.run())
But, py34 don't have await syntax. If I uploaded above source at PyPI without version constraint and someone installed it on py34, It'll work fine? How can I keep it?
Python 3 is not backwards compatible with Python 2, so your code may need to be adapted. Please start migrating your existing your existing Python 2 code to Python 3.
The Python language does not generally provide backward compatibility.
The async keyword is used to create a Python coroutine. The await keyword suspends execution of a coroutine until it completes and returns the result data. The await keywords only works within an async function.
asyncio is used as a foundation for multiple Python asynchronous frameworks that provide high-performance network and web-servers, database connection libraries, distributed task queues, etc. asyncio is often a perfect fit for IO-bound and high-level structured network code.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With