Обработка очереди с параллельными / асинхронными запросами - PullRequest
0 голосов
/ 27 августа 2018

Я хочу реализовать параллельную функцию request.get(), которая обрабатывает очередь запросов и помещает результат в список, который после завершения обрабатывается стандартным последовательным кодом. Я попробовал следующее, но мой код не заканчивается и не печатает идентификаторы.

import requests
from queue import Queue
from threading import Thread

BASE = 'http://www.uniprot.org'
KB_ENDPOINT = '/uniprot/'
FORMAT = ".xml"

num_threads = 10

ID_q = Queue()
ID_data = Queue()

# worker function
def get_ID_data(ID_q, ID_data, BASE, KB_ENDPOINT, FORMAT):
    while True:
        ID = ID_q.get()
        print(ID)
        ID_data.put(requests.get(BASE + KB_ENDPOINT + ID + FORMAT))
        ID_q.task_done()
        ID_data.task_done()

# initialize worker
for i in range(num_threads):
    worker = Thread(target=get_ID_data, args=(ID_q, ID_data, BASE, KB_ENDPOINT, FORMAT))
    worker.setDaemon(True)
    worker.start()

# load IDs and put in queue
ID_list = ["A6ZMA9", "N1P5E6",
       "H0GM11", "H0GZ91",
       "A0A0L8VK54", "G2WKA0",
       "C8ZEQ4", "B5VPH8",
       "B3LLU5", "C7GL72",
       "J8QFS9", "J8Q1C1",
       "A0A0L8RDV1"]

for ID in ID_list:
    ID_q.put(ID)

ID_q.join()

# work with ID_data
print(ID_data)

Обновление: Я изменил ответ @pkqxdd, используя asyncio и aiohttp:

import asyncio,aiohttp

IDs = ["A6ZMA9", "N1P5E6",
       "H0GM11", "H0GZ91",
       "A0A0L8VK54", "G2WKA0",
       "C8ZEQ4", "B5VPH8",
       "B3LLU5", "C7GL72",
       "J8QFS9", "J8Q1C1",
       "A0A0L8RDV1"]

BASE = 'http://www.uniprot.org'
KB_ENDPOINT = '/uniprot/'
FORMAT = ".xml"

async def get_data_coroutine(session, ID):
    async with session.get(BASE + KB_ENDPOINT + ID + FORMAT) as response:
        res = await response.text()
        print(ID)
        if not res:
            raise NameError('{} is not available'.format(ID))
        return res

async def main(loop): 
    async with aiohttp.ClientSession(loop=loop) as session:
        tasks = [get_data_coroutine(session, ID) for ID in IDs]
        return await asyncio.gather(*tasks)

loop = asyncio.get_event_loop()
result = loop.run_until_complete(main(loop))

1 Ответ

0 голосов
/ 27 августа 2018

Поскольку вы упомянули асинхронность, я предполагаю, что вы используете Python3.6 или выше.

Библиотека requests на самом деле не поддерживает асинхронное программирование, и это своего рода тупик, пытающийся сделать его асинхронным. Лучшая идея - использовать aiohttp.

Вы можете достичь своей цели с помощью простых кодов, таких как:

import asyncio,aiohttp

BASE = 'http://www.uniprot.org'
KB_ENDPOINT = '/uniprot/'
FORMAT = ".xml"

ID_list = ["A6ZMA9", "N1P5E6",
       "H0GM11", "H0GZ91",
       "A0A0L8VK54", "G2WKA0",
       "C8ZEQ4", "B5VPH8",
       "B3LLU5", "C7GL72",
       "J8QFS9", "J8Q1C1",
       "A0A0L8RDV1"]

session=aiohttp.ClientSession()
async def get_data(ID):
    async with session.get(BASE + KB_ENDPOINT + ID + FORMAT) as response:
        return await response.text()

coros=[]
for ID in ID_list:
    coros.append(get_data(ID))

loop=asyncio.get_event_loop()
fut=asyncio.gather(*coros)
loop.run_until_complete(fut)
print(fut.result())

(Да, я вижу предупреждение. Но я на самом деле не хочу усложнять ответ. Вы должны изменить его, чтобы лучше соответствовать вашим целям.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...