Ad

Issue With Sleep Inside For Loop

- 1 answer

I have a condition in my python code wherein if the condition is met, it should send an email. When the same condition is executed again, it should wait for 60 min before it can send another email. I used an if inside for loop but the issue is that the other rows in the for loop are stuck because of the if loop inside. How do I overcome this?

def send_email(previousindex,index):
    if previousindex!= index or previousindex is None:
        print('email sent')
       
    else:
        print('Wait for 1 hr')
        time.sleep(3600)


while True:
    previousindex = None
   

    for index in df.index:  # row in df.iterrows():

        if df.loc[index, 'Time flag'] == 1:
            print('fail')
            print(previousindex)
            send_email(previousindex,index)
            previousindex = index
            
        else:
            time.sleep(10)
            continue
               



    time.sleep(10)

def send_email(previous_index, index):
    if index not in previous_index:
        print('email sent')

    else:
       print(previous_index)

       print('Wait for 1 hr')
       time.sleep(3500)
       previous_index.clear()

       print('email sent')


while True:
    df = pd.read_csv(r'C:/Users/KrishnamurthyKA/Desktop/Project/Test.csv',sep = ',')

    for index in df.index:  # row in df.iterrows():

        if df.loc[index, 'Time flag'] == 1:

            print('pass')
            send_email(previous_index, index)
            previous_index.append(index)
            print(previous_index)

            # if previousindex == index:

            # print('entered if loop')
            # print(previousindex)
            # time.sleep(10)
        else:
            time.sleep(10)
            continue

    print(previous_index)
    time.sleep(10)

EDIT 2:

min = 2
 while True:
for index in df.index:
    now = datetime.datetime.now()

    if df.loc[index,'Time flag'] == 1 and df.loc[df.index[index], "Last_email_sent"] == None:
        print('pass')
        df.loc[df.index[index], "Last_email_sent"] = now
        print(now)

        #send_email(index)
    elif df.loc[index, 'Time flag'] == 1 and minutes < min:
        print('wait')
        print(minutes)
        print(df.loc[index,'Last_email_sent'])

    elif df.loc[index, 'Time flag'] == 1 and minutes >= min:
        #send_email(index)
        print('sending email after 1 min')
        df.loc[index, "Last_email_sent"] = now

        print(minutes)
        minutes = divmod((now - df.loc[index, "Last_email_sent"]).total_seconds(), 60)[0]
    else:
        print('false')


time.sleep(10)
Ad

Answer

First, your logic can be simplified into:

while True:
    previous_index = None

    for index in idx:
        # First iteration
        if condition(index) and previous_index is None:

            send_email()
            previous_index = index

        elif condition(index) and previous_index != index:

            send_email()
            previous_index = index

        elif condition(index) and previous_index == index:

            # Wait 1 hour
            time.sleep(3600)

        else:
            time.sleep(10) # Wait a bit
            continue

From my interpretation, you get stuck because the process stops during 1 hour every time it enters the time.sleep(3600). Thus during this time, you would like the rest of the loop to keep running on other index.

The problem is that time.sleep() pauses the opened python process during the time specified. One way to overcome this is to open an additional process to send the e-mail. The code would look like:

def send_email(previous_index, index):

    if previous_index != index or previous_index is None:
        # Send the e-mail
    else:
        # Wait 1 hour
        time.sleep(3600)
        # Send the e-mail

while True:
    previous_index = None

    for index in idx:
        if condition(index):

            Open_process(target = send_email, args = (previous_index, index))
            previous_index = index

        else:
            time.sleep(10) # Wait a bit
            continue

Processes have the disadvantage to be a bit slow to open. Threads might be better, however, as you included a sleep of 10 second between each loop, I don't think it matters in this application.

Finally, you can look at the library multiprocessing to manage processes.

EDIT:

def send_email(index):
    # Function sending the e-mail
    print ("e-mail sent")

# Each index is unique and the loop is executed every 10 s
# Key: index; Value: number of iterations; 360 iterations = 1 hour.
tracking = dict()
# Initialize with None
for index in df.index:
    tracking[index] = None

while True:

    for index in df.index:

        if df.loc[index, 'Time flag'] == 1 and tracking[index] is None:
            send_email(index)
            tracking[index] = 1

        elif df.loc[index, 'Time flag'] == 1 and tracking[index] < 360:
            tracking[index] += 1

        elif df.loc[index, 'Time flag'] == 1 and tracking[index] == 360:
            send_email(index)
            tracking[index] = 1 # Reset since an e-mail is sent.

        else:
            # df.loc[index, 'Time flag'] == 0
            tracking[index] = None

    time.sleep(10)

EDIT 2

    def send_email(index):
        # Function sending the e-mail
        print ("e-mail sent")

    # Add column to keep tack of last e-mail send timing
    # If the e-mail has never been sent, initialize to Nan, None, or -1
    # No idea what is more convenient, but adapt the first if accordingly
    df.add_column("Last e-mail sent timing")

    while True:

        for index in df.index:

            if df.loc[index, 'Time flag'] == 1 and df[index, "Last e-mail sent timing"] is None:
                send_email(index)
                df[index, "Last e-mail sent timing"] = current.time()

            elif df.loc[index, 'Time flag'] == 1 and current.time - df[index, "Last e-mail sent timing"] < 1 hour:
                # skip
                continue

            elif df.loc[index, 'Time flag'] == 1 and current.time - df[index, "Last e-mail sent timing"] >= 1 hour:
                send_email(index)
                df[index, "Last e-mail sent timing"] = current.time()

        time.sleep(10)

EDIT 3:

duration_to_wait = 2 # in MINUTES

while True:

    for index in df.index:

        if df.loc[index,'Time flag'] == 1 and df.loc[df.index[index], "Last_email_sent"] == None:
            send_email(index)
            df.loc[df.index[index], "Last_email_sent"] = datetime.datetime.now()

        elif df.loc[index, 'Time flag'] == 1 and datetime.datetime.now() - df.loc[df.index[index], "Last_email_sent"] < datetime.timedelta(minutes=duration_to_wait):
            print('Wait')
            print(datetime.datetime.now() - df.loc[df.index[index], "Last_email_sent"])

        elif df.loc[index, 'Time flag'] == 1 and datetime.datetime.now() - df.loc[df.index[index], "Last_email_sent"] >= datetime.timedelta(minutes=duration_to_wait):
            send_email(index)
            df.loc[index, "Last_email_sent"] = datetime.datetime.now()

        else:
            print('false')

    time.sleep(10)
Ad
source: stackoverflow.com
Ad