我正在编写一个从网站(eve-central.com)下载数据的程序。当我发送带有一些参数的GET请求时,它返回xml。问题是我需要发出大约7080个这样的请求,因为我不能多次指定typeid
参数。
def get_data_eve_central(typeids, system, hours, minq=1, thread_count=1):
import xmltodict, urllib3
pool = urllib3.HTTPConnectionPool('api.eve-central.com')
for typeid in typeids:
r = pool.request('GET', '/api/quicklook', fields={'typeid': typeid, 'usesystem': system, 'sethours': hours, 'setminQ': minq})
answer = xmltodict.parse(r.data)
当我刚刚连接到网站并提出所有请求时,它真的很慢,所以我决定让它一次使用多个线程(我读过如果进程需要大量等待(I / O,HTTP请求) ),多线程可以加速很多)。我使用多个线程重写了它,但它不知道它是否更快(实际上有点慢)。这里是使用多线程重写的代码:
def get_data_eve_central(all_typeids, system, hours, minq=1, thread_count=1):
if thread_count > len(all_typeids): raise NameError('TooManyThreads')
def requester(typeids):
pool = urllib3.HTTPConnectionPool('api.eve-central.com')
for typeid in typeids:
r = pool.request('GET', '/api/quicklook', fields={'typeid': typeid, 'usesystem': system, 'sethours': hours, 'setminQ': minq})
answer = xmltodict.parse(r.data)['evec_api']['quicklook']
answers.append(answer)
def chunkify(items, quantity):
chunk_len = len(items) // quantity
rest_count = len(items) % quantity
chunks = []
for i in range(quantity):
chunk = items[:chunk_len]
items = items[chunk_len:]
if rest_count and items:
chunk.append(items.pop(0))
rest_count -= 1
chunks.append(chunk)
return chunks
t = time.clock()
threads = []
answers = []
for typeids in chunkify(all_typeids, thread_count):
threads.append(threading.Thread(target=requester, args=[typeids]))
threads[-1].start()
threads[-1].join()
print(time.clock()-t)
return answers
我所做的是将所有typeids
分成与我想要使用的线程数量一样多的块,并为每个块创建一个线程来处理它。问题是:什么可以减缓它? (我为我糟糕的英语道歉)
答案 0 :(得分:2)
Python有Global Interpreter Lock。这可能是你的问题。实际上Python无法以真正的并行方式实现。您可能会考虑切换到其他语言或使用Python,但使用基于进程的并行性来解决您的任务。这是一个很好的演示Inside the Python GIL