How a geek tells his wife he loves her: an exercise in Python programming

October 17, 2010 | Programming Languages, Python | By: Mark VandeWettering

I’m away from my better half this weekend, visiting my Mom and brother. I scheduled this a few weeks ago, but shortly after Carmen was granted an entry into the Nike Women’s Half Marathon on the same weekend. Rescheduling the visit with Mom would have been hard, so I decided to go anyway, and missed the opportunity to cheer her on.

But I’m a geek. On Saturday night, I hit upon a brilliant, romantic idea (or what passes for one when you are a geek). I knew I was gonna be busy during her run, so I decided to write a script that would text her ever half an hour with an encouraging message. That way, even if I got busy, she’d know I was thinking about her.

It probably would have helped had I started before 10:00pm on Saturday.

First of all, it’s pretty straightforward to send texts to someone using email. If you send an email to, the contents will get routed to the person. And using Python’s smtplib, sending email is pretty easy. Here’s a function that worked for me:

def emailtxt(addr, msg):
    server = smtplib.SMTP("", 587)
    server.login("", "mypassword")
    server.sendmail("", addr, msg)

I decided to use my gmail account, but you can use whatever SMTP mail server you like.

So, now that I had a function to txt her, how to handle the scheduling? It turns out that Python has an interesting library called sched which can be used to implement a scheduler. Here’s the interesting bits:

import sched
import time

scheduler = sched.scheduler(time.time, time.sleep)

def timefor(t):
    tp = time.strptime(t, "%a %b %d %H:%M:%S %Z %Y")
    return time.mktime(tp)

scheduler.enterabs(timefor("Sun Oct 17 04:00:00 PDT 2010"), 1, sendit, (0,))
scheduler.enterabs(timefor("Sun Oct 17 04:30:00 PDT 2010"), 1, sendit, (1,))
scheduler.enterabs(timefor("Sun Oct 17 05:00:00 PDT 2010"), 1, sendit, (2,))
scheduler.enterabs(timefor("Sun Oct 17 05:30:00 PDT 2010"), 1, sendit, (3,))
scheduler.enterabs(timefor("Sun Oct 17 06:00:00 PDT 2010"), 1, sendit, (4,))
scheduler.enterabs(timefor("Sun Oct 17 06:30:00 PDT 2010"), 1, sendit, (5,))

So, what does this do? It creates a scheduler object, which operates in real time (the time.time and time.delay functions are abstract functions that implement a time and delay function). It then uses the utility function timefor to figure out the absolute time when I wanted the event to occur, and when that time expires, it will call sendit, passing it the args in parens (which in my case is a message number in a table of nice things to send her, which I’ve omitted since they are too precious for words). When the run() method is called, the scheduler will wait until the appropriate time, and then make the calls.

I had it set to start sending messages at 4:00AM, since that is when she was going to wake up. Sadly, I screwed up the code slightly, and she didn’t get her first message until 7:30 or so. But she was successfully encourage every 30 minutes after that.

I’m very proud of her and her half-marathon performance. Neither of us are natural athletes, but she’s a constant inspiration to me, and makes me want to be stronger and better.

It’s too bad I’m such a geek.


Comment from Gus
Time 10/18/2010 at 12:19 am

Thank you for sharing this. Interesting approach.

Comment from Shannon Nelson
Time 10/18/2010 at 8:32 pm

Hmmm, which is more important: the message, or the medium? I found the message to be more important when I did this and did a quick-and-dirty in bash. This doesn’t vary the message and it depends on a correctly configured mailer, but it worked very nicely.

while [[ $counter > 0 ]] ; do
echo “Happy Valentine’s Day – I love you!” | mail $herphone
(( counter= $counter – 1 ))
sleep 3600

Of course, a simple crontab entry could have been just as effective, takes only one line, and would repeat every year:

# m h d M dow command
13 9,10,11,12,13,14,15,16 14 2 * echo “Happy Valentine’s Day – I love you!” | mail

Comment from vad
Time 3/19/2013 at 3:50 am

Awesome!!! That’s putting python to a handy use.
Thanks for sharing the code snippet along with the idea. 🙂