Python 同时发送HTTP请求
我希望向API端点发送100K-300K POST请求——这些请求来自我正在迭代的JSON对象列表。不幸的是,我能使用的最大块大小是一次10个事件,这大大降低了发送我想要的所有事件的速度。定义JSON对象列表后:Python 同时发送HTTP请求,python,python-requests,python-multithreading,Python,Python Requests,Python Multithreading,我希望向API端点发送100K-300K POST请求——这些请求来自我正在迭代的JSON对象列表。不幸的是,我能使用的最大块大小是一次10个事件,这大大降低了发送我想要的所有事件的速度。定义JSON对象列表后: chunkSize= 10 for i in xrange(0, len(list_of_JSON), chunkSize): chunk = list_of_JSON[i:i+chunkSize] #10 endpoint = "" d_profile = "
chunkSize= 10
for i in xrange(0, len(list_of_JSON), chunkSize):
chunk = list_of_JSON[i:i+chunkSize] #10
endpoint = ""
d_profile = "[" + ",".join(json.dumps(x) for x in chunk) + "]"
str_event = d_profile
try:
url = base_api + endpoint + "?api_key=" + api_key + "&event=" + str_event
r = requests.post(url)
print r.content
print i
except:
print 'failed'
这个过程非常缓慢地发送事件。我已经研究了多线程/并发/和并行处理的可能性,尽管我对这一主题完全陌生。经过一些研究,我想出了一个丑陋的笑话:
import logging
import threading
import time
logging.basicConfig(level=logging.DEBUG,
format='[%(levelname)s] (%(threadName)-10s) %(message)s',
)
def worker():
logging.debug('Starting')
import time
chunkSize= 10
for i in xrange(0, (len(list_of_JSON)/2), chunkSize):
chunk = list_of_JSON[i:i+chunkSize] #10
endpoint = ""
d = "[" + ",".join(json.dumps(x) for x in chunk) + "]"
str_event = d
try:
url = base_api + endpoint + "?api_key=" + api_key + "&event=" + str_event
r = requests.post(url)
print r.content
print i
except:
print 'failed'
time.sleep(2)
logging.debug('Exiting')
def my_service():
logging.debug('Starting')
import time
chunkSize= 10
for i in xrange(((len(list_of_JSON)/2)+1), len(list_of_JSON), chunkSize):
chunk = list_of_JSON[i:i+chunkSize] #10
endpoint = ""
d = "[" + ",".join(json.dumps(x) for x in chunk) + "]"
str_event = d
try:
url = base_api + endpoint + "?api_key=" + api_key + "&event=" + str_event
r = requests.post(url)
print r.content
print i
except:
print 'failed'
time.sleep(3)
logging.debug('Exiting')
t = threading.Thread(target=my_service)
w = threading.Thread(target=worker)
w.start()
t.start()
如有任何建议或重构,将不胜感激
编辑:我相信我的实现实现了我想要的。我已经看过了,但是仍然不确定这个解决方案有多好或者效率有多高 您可以使用scrapy,它按照注释中的建议使用twisted。Scrapy是一个用于抓取网页的框架,但您也可以使用它发送post请求。实现与代码相同功能的爬行器大致如下所示:
class EventUploader(scrapy.Spider):
BASE_URL = 'http://stackoverflow.com/' # Example url
def start_requests(self):
for chunk in list_of_JSON:
get_parameters = {
'api_key': api_key,
'event': json.dumps(chunk), # json.dumps can encode lists too
}
url = "{}/endpoint?{}".format(
self.BASE_URL, urlencode(get_parameters))
yield scrapy.FormRequest(url, formdata={}, callback=self.next)
def next(self, response):
# here you can assert everything went ok
pass
scrapy runspider my_spider.py
一旦你的爬行器就位,你就可以使用scrapy中间件来限制你的请求。您可以这样运行上载程序:
class EventUploader(scrapy.Spider):
BASE_URL = 'http://stackoverflow.com/' # Example url
def start_requests(self):
for chunk in list_of_JSON:
get_parameters = {
'api_key': api_key,
'event': json.dumps(chunk), # json.dumps can encode lists too
}
url = "{}/endpoint?{}".format(
self.BASE_URL, urlencode(get_parameters))
yield scrapy.FormRequest(url, formdata={}, callback=self.next)
def next(self, response):
# here you can assert everything went ok
pass
scrapy runspider my_spider.py
这可能是一个很老的复制品,我建议研究类似的东西。文档中有一些基本的示例可以完全满足您的要求。请查看eventlet,谢谢。实际上,该链接上的第一个答案使用了线程,这仍然是相关的。以及twisted,它提供异步请求。多处理可以在与第一个答案相同的结构中使用,而不是线程。请注意:只要请求生成遵循闭环设计,请求速率就会受到并发线程数量以及每个请求的响应时间的限制。Async可以避免这种情况,但理解它通常是非常重要的。