2013-12-17 8 views
6

मैं एक एपीआई में हजारों कॉल करना चाहता हूं जो प्रतिक्रिया प्राप्त करने के लिए सेकंड की धीमी गति से है। एकमात्र सीमा यह है कि मैं प्रति सेकंड एक से अधिक अनुरोध कर सकता हूं। ऐसा करने का सबसे अच्छा तरीका क्या है? मुझे लगता है कि निम्नलिखित कोड काम करता है, लेकिन मुझे लगता है कि मुझे किसी भी तरह थ्रेडिंग लाइब्रेरी का बेहतर उपयोग करने में सक्षम होना चाहिए। मैं अजगर 3,3एक धीमी एपीआई को हजारों कॉल करने के लिए पाइथन थ्रेड का उपयोग दर सीमा

last_job = datetime.now() 
for work in work_list: 
    while (datetime.now()-last_job).total_seconds() < 1 or threading.active_count() >= max_threads: 
     time.sleep(.1) 
    threading.Thread(target=work_function, args=[work]).start() 
    last_job = datetime.now() 
+0

मैं सही है कि आप एक बना सकते हैं मिला प्रति सेकंड अनुरोध, इसलिए जब आप पहली क्वेरी परिणाम के लिए 20 सेकंड प्रतीक्षा करते हैं, तो आप 1 9 को तुरंत चालू कर सकते हैं? क्या उन अतिरिक्त 1 9 प्रश्नों में पहले व्यक्ति के लिए प्रतिक्रिया धीमी नहीं होगी? – alko

+0

नौकरियों को कतारबद्ध करने और दर सीमा निर्धारित करने के लिए सेलरी का उपयोग क्यों नहीं करें? – adam

+1

@adam यह इस काम के लिए थोड़ा अधिक नहीं है? – alko

उत्तर

11

उपयोग कर रहा हूँ आप एक थ्रेड पूल निश्चित-आकार का उपयोग करते हुए नौकरियों का एक समूह को चलाना चाहते हैं, तो आप इस तरह concurrent.futures.ThreadPoolExecutor उपयोग कर सकते हैं,:

from concurrent.futures import ThreadPoolExecutor 
with ThreadPoolExecutor(max_workers=5) as executor: 
    for work in work_list: 
     executor.submit(work_function, work) 

आप यह सुनिश्चित करना चाहते हैं कि आप एक से अधिक एपीआई कॉल करते हैं, तो आपको इसे अपने work_function के अंदर से करने की ज़रूरत है। नौकरी जमा करते समय आप ऐसा नहीं कर सकते हैं, क्योंकि आप नहीं जानते कि नौकरी कब तक पहुंचने के लिए इंतजार कर रही है।

तो यह मेरे थे, मैं इतना है कि यह पुन: प्रयोज्य है अपने ही वर्ग में कोड सीमित दर डाल चाहते हैं:

from collections import Iterator 
from threading import Lock 
import time 

class RateLimiter(Iterator): 
    """Iterator that yields a value at most once every 'interval' seconds.""" 
    def __init__(self, interval): 
     self.lock = Lock() 
     self.interval = interval 
     self.next_yield = 0 

    def __next__(self): 
     with self.lock: 
      t = time.monotonic() 
      if t < self.next_yield: 
       time.sleep(self.next_yield - t) 
       t = time.monotonic() 
      self.next_yield = t + self.interval 

api_rate_limiter = RateLimiter(1) 

def work_function(work): 
    next(api_rate_limiter) 
    call_api(...) 

time.monotonic अजगर 3.3 में पेश किया गया था; अजगर के पुराने संस्करणों में आप time.time इस्तेमाल कर सकते हैं लेकिन यह पीछे की ओर जब सिस्टम घड़ी परिवर्तन है, तो आप यह सुनिश्चित करें कि इस लंबा सोता का कारण नहीं है की आवश्यकता होगी कूद कर सकते हैं:

   time.sleep(min(self.next_yield - t, self.interval)) 
+1

यह खूबसूरती से काम करता है, धन्यवाद। –

संबंधित मुद्दे