gpt4 book ai didi

python - python 中的协程在 3.4 和 3.5 之间,如何保持向后兼容性?

转载 作者:太空狗 更新时间:2023-10-29 18:02:55 25 4
gpt4 key购买 nike

我正在使用 asyncio 开发 python 聊天机器人框架。但是我看PEP-492还有新的语法,async/await,最后它被接受了。

我喜欢 async/await 语法,我想使用它。但我担心 3.4 backwords 兼容性。

如果我在我的代码中使用新语法,有人可以在 3.4 中使用它吗?

比如我写了这样一段代码,

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 中将其与此源一起使用

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 上,它会正常工作吗?我该如何保留它?

最佳答案

如果您需要在代码中支持 Python 3.4,则需要使用旧的 @asyncio.coroutine/yield from 样式语法。如果不运行 3.5,就无法支持 async/await 语法;你将在 3.4 或更低版本的编译时得到一个 SyntaxError

以向后兼容的方式利用您可以做的新功能的唯一一件事就是在适当的地方将各种__a*__方法添加到您的类中( __aiter____aenter____aexit__ 等),使用 yield from 协程语法。这样,您的对象就可以支持 async with/async for 语句,这样运行 Python 3.5 的库用户就可以利用这些新功能。

例如,此类可以与 async with 一起使用,但在 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 上:

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 上

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 的应用程序,这可能没有用,但如果您正在开发一个旨在供其他开发人员使用的库或框架,则值得这样做。

关于python - python 中的协程在 3.4 和 3.5 之间,如何保持向后兼容性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30191556/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com