I'm trying to send a data frame to myself daily via email. I've gotten this far and everything works but when I try to send it at a specific time I get this error
'the first argument must be callable' - referencing the fact that I'm calling a function within the parentheses.
Any ways to fix this? Also now that I have this set up, if I close my program, will it continue to run the script so that it executes daily?
Thanks,
def email_new(df):
message = MIMEMultipart()
message['Subject'] = "Subject"
message['From'] = '[email protected]'
message['To'] = '[email protected]'
html = MIMEText(df.to_html(index=False), "html")
message.attach(html)
with smtplib.SMTP("smtp.office365.com", 587) as server:
server.starttls()
server.login('[email protected]','password')
server.sendmail('[email protected]', 'email.edu', message.as_string())
schedule.every().day.at('17:40').do(email_new(df))
while True:
schedule.run_pending()
time.sleep(1)
CodePudding user response:
do()
takes the arguments to pass to the function in a second parameter:
schedule.every().day.at('17:40').do(email_new,df)
CodePudding user response:
I'm not familiar with this .do
method, but in general, you can partially instantiate your email_new
function using functools.partial
. In this way, you can just pass your partially instantiated email_new
function directly to the .do
method.
Let's start with a toy example:
from functools import partial
def add_two_numbers(x, y):
return x y
add_5_10 = partial(add_two_numbers, 5, 10)
print(add_5_10()) # 15
Now with your example:
from functools import partial
def email_new(df):
message = MIMEMultipart()
message['Subject'] = "Subject"
message['From'] = '[email protected]'
message['To'] = '[email protected]'
html = MIMEText(df.to_html(index=False), "html")
message.attach(html)
with smtplib.SMTP("smtp.office365.com", 587) as server:
server.starttls()
server.login('[email protected]','password')
server.sendmail('[email protected]', 'email.edu', message.as_string())
email_new_df = partial(email_new, df)
schedule.every().day.at('17:40').do(email_new_df)
while True:
schedule.run_pending()
time.sleep(1)
As for scheduling while you're away from your laptop, I'd recommend learning about Cron Jobs. However, your laptop must be awake and able to perform the process. In this case, perhaps a remote computer or a Raspberry Pi might be a good idea.
CodePudding user response:
See the schedule module examples for passing arguments to your function here: https://schedule.readthedocs.io/en/stable/examples.html#pass-arguments-to-a-job
You pass arguments for your function as additional parameters to the do
method. For your schedule you would use
schedule.every().day.at('17:40').do(email_new, df)