Используйте метод .on()
jQuery http://api.jquery.com/on/ для присоединения обработчиков событий к элементу live.
Также с версии 1.9 .live()
удаляется.
Если какой-то метод использует что-то асинхронное, оно также должно быть явно определено как асинхронное. Это основная идея, лежащая в основе asyncio
: заставить вас писать код так, как вы всегда знаете, может ли какой-нибудь произвольный метод сделать что-то асинхронное.
В своем фрагменте вы хотите сделать асинхронную вещь (bar
I / O) внутри метода синхронизации __init__
и asyncio
запрещает это. Вы должны сделать _run_coro
асинхронным и инициализировать Foo
асинхронно, например, , используя метод __await__
:
import asyncio
class Foo:
def __await__(self):
return self._run_coro().__await__()
async def _run_coro(self): # real async initializer
async def init():
await asyncio.sleep(1) # bar I/O
self.bar = 123
await init()
return self
async def spam(self):
return await asyncio.sleep(1) # I/O op
async def main():
foo = await Foo()
await foo.spam()
asyncio.run(main()) # instead of two lines in Python 3.7+
Возможно, вам будет интересно прочитать этот ответ [ 1120], чтобы лучше понять, как asyncio
работает и как с этим справляться.
Upd:
blockquote>s = self.init_async_session() try: s.send(None)
Не делайте таких вещей: метод генератора - это только детали реализации в отношении сопрограмм. Вы можете предсказать, как сопрограмма отреагирует на вызов метода
.send()
, и вы можете положиться на это поведение.Если вы хотите выполнить сопрограмму, используйте
await
, если вы хотите запустить ее «в фоновом режиме», используйте task или другие функции изasyncio
doc .Как правильно инициализировать
blockquote>self.async_session
Когда дело доходит до
aiohttp.ClientSession
, его следует не только создавать, но и правильно закрывать. Лучший способ сделать это - использовать асинхронный менеджер контекста, как показано вaiohttp
doc .Если вы хотите скрыть эту операцию внутри
Foo
, вы также можете сделать ее асинхронным менеджером. Полный пример:import aiohttp class Foo: async def __aenter__(self): self._session = aiohttp.ClientSession() await self._session.__aenter__() return self async def __aexit__(self, *args): await self._session.__aexit__(*args) async def spam(self): url = 'http://httpbin.org/delay/1' resp = await self._session.get(url) text = await resp.text() print(text) async def main(): async with Foo() as foo: await foo.spam() asyncio.run(main())
Upd2:
Вы можете комбинировать способы инициализации / закрытия объекта сверху для достижения желаемого результата. Пока вы помните, что обе операции асинхронны и, следовательно, их следует ожидать, все должно быть в порядке.
Еще один возможный путь:
import asyncio import aiohttp class Foo: def __await__(self): return self._init().__await__() async def _init(self): self._session = aiohttp.ClientSession() await self._session.__aenter__() return self async def close(self): await self._session.__aexit__(None, None, None) async def spam(self): url = 'http://httpbin.org/delay/1' resp = await self._session.get(url) text = await resp.text() print(text) async def main(): foo = await Foo() try: await foo.spam() finally: await foo.close() asyncio.run(main())
Вот мое решение.
class Session:
def __init__(self, headers):
self._headers = headers
self._session = requests.Session()
self._async_session = None
async def _init(self):
self._session = aiohttp.ClientSession(headers=headers)
async def async_request(self, url):
while True:
try:
async with self._async_session.get(url) as resp:
resp.raise_for_status()
return await resp.text()
except aiohttp.client_exceptions.ClientError:
#retry or raise
except AttributeError:
if isinstance(self._async_session, aiohttp.ClientSession):
raise
await self._init()
def request(self, url):
return self._session.get(url).text
async def close(self):
if isinstance(self._async_session, aiohttp.ClientSession):
await self._session.close()
async def main():
session = Session({})
print(await session.async_request('https://httpstat.us/200')
await session.close()
asyncio.run(main())
Я могу инициализировать класс Session
и делать как синхронные, так и асинхронные запросы. Мне не нужно явно вызывать await session._init()
для инициализации self._async_session
, как, когда вызывается session._async_request
и self._async_session
- Нет, тогда будет вызван await session._init()
и запрос будет повторен.