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