非同期API があり、これを使用してSMTPサーバーにメールを接続して送信します。したがって、Python 3のcontextmanager
。からのcontextlib
を使用することにうまく適合します。
ただし、どちらもジェネレーター構文を使用して記述するため、書き込みが可能かどうかはわかりません。
これは問題を示すかもしれません(非同期呼び出しとコンテキストマネージャーへのyieldの違いを示すために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()
このようなことはpython現在ですか?そしてwith
as
ステートメントが使用されている場合、どのように使用しますか?これ-多分古いスタイルのコンテキストマネージャを使用している?
@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()
使用法:
async with SMTPConnection(url, port, username, password) as client:
await client.sendmail(...)
バカなことをしてしまったら、気軽に指摘してください。
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()
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()
そして、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()
asyncio_extras パッケージには、これに対する素晴らしいソリューションがあります:
_import asyncio_extras
@asyncio_extras.async_contextmanager
async def smtp_connection():
client = SMTPAsync()
...
_
Python <3.6の場合、 async_generator パッケージも必要で、_yield client
_をawait yield_(client)
に置き換えます。