Python : class programming and queuing

北城余情 提交于 2021-02-08 09:35:11

问题


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


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/65738427/python-class-programming-and-queuing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!