fre*_*bie 31 python asynchronous contextmanager
我有一个异步API,我用它连接并发送邮件到SMTP服务器,它有一些设置和拆除它.所以它很适合使用contextmanagerPython 3的contextlib.
虽然,我不知道它是否可能写,因为它们都使用生成器语法来编写.
这可能会证明问题(包含yield-base和async-await语法的混合,以演示异步调用和上下文管理器的收益之间的差异).
@contextmanager
async def smtp_connection():
client = SMTPAsync()
...
try:
await client.connect(smtp_url, smtp_port)
await client.starttls()
await client.login(smtp_username, smtp_password)
yield client
finally:
await client.quit()
Run Code Online (Sandbox Code Playgroud)
目前python中有可能出现这种情况吗?with as如果是,我将如何使用声明?如果没有,我可以用另一种方式实现这一点 - 也许使用旧式上下文管理器?
Nat*_*ith 41
在Python 3.7中,您将能够编写:
from contextlib import asynccontextmanager
@asynccontextmanager
async def smtp_connection():
client = SMTPAsync()
...
try:
await client.connect(smtp_url, smtp_port)
await client.starttls()
await client.login(smtp_username, smtp_password)
yield client
finally:
await client.quit()
Run Code Online (Sandbox Code Playgroud)
在3.7发布之前,您可以使用此async_generator包.在3.6上,你可以写:
# This import changed, everything else is the same
from async_generator import asynccontextmanager
@asynccontextmanager
async def smtp_connection():
client = SMTPAsync()
...
try:
await client.connect(smtp_url, smtp_port)
await client.starttls()
await client.login(smtp_username, smtp_password)
yield client
finally:
await client.quit()
Run Code Online (Sandbox Code Playgroud)
如果你想一直回到3.5,你可以写:
# This import changed again:
from async_generator import asynccontextmanager, async_generator, yield_
@asynccontextmanager
@async_generator # <-- added this
async def smtp_connection():
client = SMTPAsync()
...
try:
await client.connect(smtp_url, smtp_port)
await client.starttls()
await client.login(smtp_username, smtp_password)
await yield_(client) # <-- this line changed
finally:
await client.quit()
Run Code Online (Sandbox Code Playgroud)
fre*_*bie 21
感谢@jonrsharpe能够创建一个异步上下文管理器.
对于想要一些示例代码的人来说,这就是我的最终结果:
class SMTPConnection():
def __init__(self, url, port, username, password):
self.client = SMTPAsync()
self.url = url
self.port = port
self.username = username
self.password = password
async def __aenter__(self):
await self.client.connect(self.url, self.port)
await self.client.starttls()
await self.client.login(self.username, self.password)
return self.client
async def __aexit__(self, exc_type, exc, tb):
await self.client.quit()
Run Code Online (Sandbox Code Playgroud)
用法:
async with SMTPConnection(url, port, username, password) as client:
await client.sendmail(...)
Run Code Online (Sandbox Code Playgroud)
如果我做了任何愚蠢的事,请随时指出.
该asyncio_extras包有这个很好的解决方案:
import asyncio_extras
@asyncio_extras.async_contextmanager
async def smtp_connection():
client = SMTPAsync()
...
Run Code Online (Sandbox Code Playgroud)
对于Python <3.6,您还需要async_generator包并替换yield client为await yield_(client).
| 归档时间: |
|
| 查看次数: |
13977 次 |
| 最近记录: |