python中的协程在3.4和3.5之间,如何保持backword的兼容性? [英] Coroutine in python between 3.4 and 3.5, How can I keep backwords compatibility?
问题描述
我正在使用asyncio
开发python聊天机器人框架.但是我看到 PEP-492 ,并且有新的语法async
/await
并最终接受了.
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.
我喜欢async
/await
语法,我想使用它.但我担心3.4个Backwords的兼容性.
I like async
/await
syntax and I want to use it. but I worry about 3.4 backwords compatibility.
如果我在代码中使用新语法,那么有人可以在3.4中使用它吗?
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)
然后,我可以将其与py35中的此源一起使用
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())
但是,py34没有await
语法.如果我在没有版本限制的情况下将上述源代码上传到PyPI,并且有人将其安装在py34上,那么可以正常工作吗?我该如何保存?
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.4,则需要使用旧的@asyncio.coroutine
/yield from
样式语法.如果不运行3.5,就无法支持async
/await
语法.您将在编译时获得3.4或更低版本的SyntaxError
.
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.
唯一使用向后兼容的新功能的方法是在适当的情况下向类中添加各种__a*__
方法(__aiter__
,__aenter__
,__aexit__
等),使用yield from
协程语法.这样,您的对象可以支持async with
/async for
语句,以便运行Python 3.5的库用户可以利用这些新功能.
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.
例如,此类可与async with
一起使用,但在Python 3.4上运行时不会中断:
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)
在Python 3.5上:
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())
在Python 3.4上
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())
如果您正在编写使用asyncio
的应用程序,那么这可能没有用,但是如果您正在开发打算供其他开发人员使用的库或框架,那是值得做的.
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.
这篇关于python中的协程在3.4和3.5之间,如何保持backword的兼容性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!