for循环内的睡眠问题

Issue with sleep inside for loop

我的 python 代码中有一个条件,如果满足条件,它应该发送电子邮件。当再次执行相同的条件时,它应该等待 60 分钟才能发送另一封电子邮件。我在 for 循环中使用了 if,但问题是 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)

首先,你的逻辑可以简化为:

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

根据我的解释,您会卡住,因为每次进入 time.sleep(3600) 时进程都会停止 1 小时。因此,在此期间,您希望循环的其余部分将 运行 保留在其他索引上。

问题是 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 秒的睡眠,我认为这在这个应用程序中并不重要。

最后可以看看库multiprocessing来管理进程。

编辑:

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)