Я пытаюсь разобраться с asyncio и aiohttp, и впервые за многие годы программирование заставляет меня чувствовать себя совершенно глупым и неспособным. Что довольно красиво, в духе странного дзен. Но, увы, есть над чем поработать.
У меня есть существующий класс, который может делать множество удивительных вещей в Интернете, таких как регистрация на веб-сайте, получение данных, работа. И теперь мне нужно около 100 или 1000 этих маленьких рабочих пчел, чтобы зарегистрироваться. Код выглядит примерно так:
class Worker(object):
def signup(self, ...):
...
data = self.make_request(url, data)
self.user_id = data.get("user_id")
return self
def make_request(self, url, data):
response = requests.post(url, data=data)
return response.json()
workers = [Worker().signup() for n in range(100)]
Как видите, мы используем модуль запросов для выполнения POST-запроса. Однако это блокировка, поэтому нам придется подождать, пока работник N завершит регистрацию, прежде чем мы начнем регистрировать работника N+1. К счастью, первоначальный автор класса Worker (это звучит очаровательно по-марксистски) в своей бесконечной мудрости заворачивал каждый HTTP-вызов в метод self.make_request
, поэтому сделать весь Worker неблокирующим можно просто путем замены библиотеки запросов на неблокирующую. блокирует один ааааааааааааааа твой дядя боб, да? Вот как далеко я продвинулся:
class AyncWorker(Worker):
@asyncio.coroutine
def make_request(self, url, data):
response = yield from aiohttp.request('post', url, data=data)
return (yield from response.json())
coroutines = [Worker().signup() for n in range(100)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(coroutines))
loop.close()
Но это поднимет AttributeError: 'generator' object has no attribute 'get'
в методе signup
, где я делаю self.user_id = data.get("user_id")
. Кроме того, у меня до сих пор нет рабочих слов в аккуратном словаре. Я знаю, что я, скорее всего, совершенно неправильно понимаю, как работает asyncio, но я уже провел день, читая различные документы, умопомрачительные учебники Дэвида Бизли и массу игрушечных примеров, которые достаточно просты, чтобы я понял их и слишком просто применить в этой ситуации. Как мне структурировать моего воркера и мой асинхронный цикл, чтобы зарегистрировать 100 воркеров параллельно и в конечном итоге получить список всех воркеров после их регистрации?
signup
должен быть сопрограммой, которая делает что-то вродеdata = yield from self.make_request(url, data)
. Все, что вы возвращаете в сопрограмме asyncio, должно использоваться только сyield from
. - person x3al   schedule 28.10.2014