Reputation: 45
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)
Upvotes: 1
Views: 607
Reputation: 5756
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)
Upvotes: 5