1

I facing a problem. I found a solution I'm explaining below but I want some advice aout to right way to resolve it.

Here is the problem:

I have a class object called Item. This Item has a method, call make_request which makes a GET request on a server, and save the result. Now, I have implemented 3 Item object which calls make_request. The Item objects gonna call the method each 3 minutes, but these make_requests must be delayed by 1 minutes from the previous object's call.

Example :

  • 14:00 - Item0.make_request
  • 14:01 - Item1.make_request
  • 14:02 - Item2.make_request
  • 14:03 - Item0.make_request
  • 14:04 - Item1.make_request
  • 14:05 - Item2.make_request
  • 14:06 - Item0.make_request
  • 14:07 - Item1.make_request
  • 14:08 - Item2.make_request
  • 14:09 - Item0.make_request
  • 14:10 - Item1.make_request
  • 14:11 - Item2.make_request
  • 14:12 - Item0.make_request
  • 14:13 - Item1.make_request
  • 14:14 - Item2.make_request ... etc

What I do actully is a while loop where I check the time minute and call the right object's method.

from datetime import datetime

Item0 = Item(name="Item0")
Item1 = Item(name="Item1")
Item2 = Item(name="Item2")

while True:
   if str(datetime.now().time.minute[-1]) in ['0', '3', '6']: 
      Item0.make_request()
   if str(datetime.now().time.minute[-1]) in ['1', '4', '7']: 
      Item1.make_request()
   if str(datetime.now().time.minute[-1]) in ['2', '5', '8']: 
      Item2.make_request()

This is a solution, but it's not clean and I don't like it. It is also missing 1 minute. I was thinking about using Queue.

I'm waiting for your advice :)

EDIT : something more robust

Thank a lot for your answers. I found a good solution for the first problem.

Now, I'm asking myself if I can, in the same context, use a Queue. The idea is to call the make_request independently of the result of the previous make_request.

For example: At 14:00:00 I call Item0.make_request. Unfortunately, it takes more than 60 seconds to get the result of Item0.make_request but I want my Item1.make_request to be called independently at 14:01:00.

It happens sometimes

2 Answers 2

3

Usually, when you have a number of items, on which the same thing is to be done, it is best to keep them in a list:

items = [Item(name="Item0"), Item(name="Item1"), Item(name="Item2")]

Then, no special logic is needed to see which the current minute is. Just run them sequentially with 1 minute delay:

while True:
    for item in items:
        item.make_request()
        time.sleep(60)  # 60 seconds

There is one drawback, about which you may or may not care: as it is, the time between two requests will be 60 seconds plus the time taken by make_request(). There are ways to avoid that, but perhaps you don't care about such details.

Sign up to request clarification or add additional context in comments.

1 Comment

Well, it's a good solution indeed :) thank for answering me. Do you how to implement a queue using a list of items to manage the delay ? Just to know
0

I came up with something overkill and configurable according to your need.

import time


# Assuming your class
class Item:
    def __init__(self, name, number_of_ticks_to_act_in, *args, **kawrgs):
        self.name = name
        self.number_of_ticks_to_act_in = number_of_ticks_to_act_in

    def make_request(self):
        print(f"Making a requests from {self.name}")

# Item0 and Item1 will post every 2 mins and Item2 every 3 mins.
items = [Item("Item0", 2), Item("Item1", 2), Item("Item2", 3)]

# ?: Your configs
seconds_per_tick = 60 # Every tick can be in every 60 seconds or how you want it.
ticks_passed = 0 # This is a counter to keep track of ticks passed.
max_ticks_item = max(items, key=lambda i: i.number_of_ticks_to_act_in) # The counter gets set back to 0 once the max ticks that you stated have exceeded, this will let you run the code forever and never have to worry about the number surpassing int size. Overkill.
is_condition_met = True # You can set a condition to stop your forever while loop

while is_condition_met:
    # The counter is reset if it exceeds your max ticks.
    if ticks_passed >= max_ticks_item.number_of_ticks_to_act_in:
        ticks_passed = 0
    ticks_passed += 1
    time.sleep(seconds_per_tick)
    # Only Items with the same tick will get executed, this lets you have 2 or more Items of the same tick.
    for item in filter(lambda x: ticks_passed % x.number_of_ticks_to_act_in == 0,
                       items):
        item.make_request()

Hope this isn't too complicated. Added as much comments as I could.

1 Comment

Thank for your answer :) it's a good way to do it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.