Проблема со сном внутри цикла - PullRequest
1 голос
/ 07 октября 2019

У меня есть условие в моем коде Python, где, если условие выполнено, оно должно отправить электронное письмо. Когда то же самое условие выполняется снова, оно должно подождать 60 минут, прежде чем оно сможет отправить другое письмоЯ использовал цикл if внутри for, но проблема в том, что другие строки цикла for застряли из-за цикла if внутри. Как мне это преодолеть?

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)

РЕДАКТИРОВАТЬ 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)

1 Ответ

5 голосов
/ 07 октября 2019

Во-первых, ваша логика может быть упрощена до:

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

Из моей интерпретации вы застреваете, потому что процесс останавливается в течение 1 часа каждый раз, когда он входит в time.sleep(3600). Таким образом, в течение этого времени вы хотели бы, чтобы остальная часть цикла продолжала работать с другим индексом.

Проблема в том, что time.sleep() приостанавливает открытый процесс python в течение указанного времени. Один из способов преодоления этого - открыть дополнительный процесс для отправки электронной почты. Код будет выглядеть следующим образом:

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

Недостаток процессов заключается в том, что они открываются немного медленно. Тем не менее, потоки могут быть лучше, так как вы включили 10-секундную паузу между циклами, я не думаю, что это имеет значение в этом приложении.

Наконец, вы можете посмотреть на многопроцессорность библиотеки для управления процессами.

РЕДАКТИРОВАТЬ:

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)

РЕДАКТИРОВАТЬ 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)

РЕДАКТИРОВАТЬ 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)
...