Was sollte man noch verbessern?
Code: Alles auswählen
import time
import threading
import concurrent.futures
import queue
def print2(txt,*args):
    txt = str(time.time()) + ": " + txt
    print(txt,*args)
class Limiter():
 
    def __init__(self, zeitlimit, calllimit):
        self.zeitlimit = zeitlimit
        self.calllimit = calllimit # diese zahl an Calls darf innerhalb von zeitlimit sekunden gemacht werden.
        self.gemachte_anfragen =[]
        self.anfragen = queue.Queue()
        self.thread = threading.Thread(target=self.run)
 
 
    def darfich(self,a):
        e = threading.Event()
        wartezeit = []
        self.anfragen.put((e, wartezeit))
        e.wait()
        print2("darfich {} sleep {}".format(a,wartezeit[0]))
        if wartezeit[0] > 0:
            time.sleep(wartezeit[0])
           
    
    def wann_darfich(self):
        jetzt = time.time()
        anfragencopy = self.gemachte_anfragen[:] # eine Kopie machen, damit einträge entfernt werden können (gehts auch weniger fehleranfällig?)
        for timestamp in anfragencopy:
            if timestamp < jetzt - self.zeitlimit:
                self.gemachte_anfragen.remove(timestamp) # alle zu alten einträge entfernen.
        if len(self.gemachte_anfragen) < self.calllimit:
            return jetzt
            
        relevantecalls = self.gemachte_anfragen[-self.calllimit:] # auch zukünftige timestamps muessen beachtet werden
        if len(relevantecalls) < self.calllimit:
            return jetzt
        else: # es wurden soviele wie erlaubt gemacht oder gar mehr, dann warten
            return relevantecalls[0] + self.zeitlimit # relevantecalls[0] ist der timestamp des ältesten relevanten calls
            
    
    def run(self):
        count = 0
        while True:
            count += 1
            e, wartezeit = self.anfragen.get() # wartet, bis etwas vorhanden ist ... nur wie beende ich das, wenn ich es nicht mehr brauche?
            w = self.wann_darfich() # absoluter ts
            self.gemachte_anfragen.append(w)
            wartezeit.append(w-time.time())
            e.set() # e.wait() in "darfich" beenden
            if count>=7: # notmaßnahme damit der thread beendet wird
                return
                
limit = Limiter(5,2)
def test(a):
    limit.darfich(a)
    print2("test {}".format(a))
    return a
     
               
if __name__ == '__main__':  
    limit.thread.start()
    pool = concurrent.futures.ThreadPoolExecutor(7) 
    futures = []
    futures.append(pool.submit(test, 1))
    futures.append(pool.submit(test, 2))
    futures.append(pool.submit(test, 3))
    futures.append(pool.submit(test, 4))
    futures.append(pool.submit(test, 5))
    futures.append(pool.submit(test, 6))
    futures.append(pool.submit(test, 7))
    concurrent.futures.wait(futures) 
    print2("Vollständig beendet!")