#!/usr/bin/env python """ This example displays a graph of request rates over time. Requests are continuously sent to URLs randomly picked from a fixed number of possible URLs. This demonstrates how average request rate increases as the proportion of cached requests increases. Try running this example with different cache settings and URLs to see how the graph changes. """ from random import randint from time import time from rich.live import Live from rich.progress import BarColumn, MofNCompleteColumn, Progress from rich.table import Table from requests_cache import CachedSession N_UNIQUE_REQUESTS = 200 class RPSProgress(Progress): """Display a bar chart of requests per second""" def __init__(self, interval: int = 1, scale: int = 500, **kwargs): super().__init__(BarColumn(), '{task.completed}', **kwargs) self.current_task = None self.interval = interval self.interval_start = None self.scale = scale self.total_requests = 0 self.next_interval() def next_interval(self): """Create a new task to draw the next line on the bar chart""" self.current_task = self.add_task('barchart_line', total=self.scale) self.interval_start = time() def count_request(self): if time() - self.interval_start >= self.interval: self.next_interval() self.advance(self.current_task) self.total_requests += 1 class CacheRPSProgress: """Track requests per second plus cache size in a single live view""" def __init__(self, n_unique_requests: int = 100): self.rps_progress = RPSProgress() self.cache_progress = Progress( BarColumn(complete_style='blue'), '[cyan]Requests cached:', MofNCompleteColumn(), ) header = Progress(BarColumn(), '[cyan]Requests per second') header.add_task('') self.cache_task = self.cache_progress.add_task('', total=n_unique_requests) self.n_unique_requests = n_unique_requests self.start_time = time() self.table = Table.grid() self.table.add_row(header) self.table.add_row(self.rps_progress) self.table.add_row(self.cache_progress) self.live = Live(self.table, refresh_per_second=10) def __enter__(self): """Start live view on ctx enter""" self.live.__enter__() self.log( '[cyan]Measuring request rate with ' f'[white]{self.n_unique_requests}[cyan] total unique requests' ) self.log('[cyan]Press [white]Ctrl+C[cyan] to exit') return self def __exit__(self, *args): """Show stats on ctx exit""" self.live.__exit__(*args) elapsed = time() - self.start_time self.log( f'[cyan]Sent a total of [white]{self.total_requests}[cyan] ' f'requests in [white]{elapsed:.2f}[cyan] seconds ' ) self.log(f'[cyan]Average: [white]{int(self.total_requests/elapsed)}[cyan] requests/second') @property def total_requests(self): return self.rps_progress.total_requests def count_request(self): self.rps_progress.count_request() def update_cache_size(self, size: int): self.cache_progress.update(self.cache_task, completed=size) def log(self, msg: str): self.cache_progress.log(msg) def test_rps(session): session.cache.clear() # Send a request to one of a fixed number of unique URLs def random_request(): request_number = randint(1, N_UNIQUE_REQUESTS) session.get(f'https://httpbin.org/get?page={request_number}') # Show request rate over time and total cached (unexpired) requests with CacheRPSProgress(N_UNIQUE_REQUESTS) as progress: while True: try: random_request() progress.count_request() progress.update_cache_size(session.cache.responses.count(expired=False)) except KeyboardInterrupt: break if __name__ == '__main__': session = CachedSession(use_temp=True, expire_after=30) test_rps(session)