I recently wrote a a script that monitors file/dir changes, acts on a change and notifies me via notify-osd or email. While writing this I came to the conclusion that a simple thing as sending an email easily kicks up to at least 10 lines of code and some settings. So it was time to find an easier way for this.

You can of course create distributable modules or packages but with simple local workstation like maintenance this seems overkill … yep, you are allowed to disagree 😉

So, we need a place to put code that is easy to import in our used scripts and it should be easy to maintain. Dropping it in my homedir in a directory called “.python” seems well suited for this.

The Setup

Create the directory “.python” in your $HOMEDIR. Then add a line to your “.bashrc” to export $PYTHONPATH so when you do an import in python it is actually found.


Python picks up the paths from this variable and adds them to “sys.path” so there’s no need to add the path in every script you make. In individual cases you can of course do it like it is explained here.

Then create a file in “~/.python/” for instance “userconfig.py”.

To make it available in your script simply import it and execute one of your functions.

import userconfig as mystuff
mystuff.function(with, parms)

I’ll give an example of a userconfig.py function to easily send out emails.

import os
import sys
import pynotify
import smtplib
from email.mime.text import MIMEText

# Settings << These are the "Sensible defaults" :)
MAILSERVER = 'localhost'
MAILFROM = 'somebody'
MAILTO = 'you@yourdomain.com'

def send_mail(subject, body, fro=MAILFROM, to=MAILTO):
    Stripped function to send mail from local code
    msg = MIMEText(body)
    msg['Subject'] = subject
    msg['From'] = fro
    msg['To'] = to

    s = smtplib.SMTP(MAILSERVER)
    s.sendmail(msg['From'], msg['To'], msg.as_string())

The code above composes and sends an email. Doing all this in the script you are writing results in quite a bunch of these lines ending up in every one of your scripts.

Sensible defaults

How about not having to enter those ‘always the same defaults’? Well … When using the setup described in this article most can be omitted and parameters only need to be added when you deviate from your sensible defaults.

For argument sake I’ll give an example script that just mails something and calls the “send_mail()” function.

import userconfig as user

body = """Some multiline triple quoted body massnnwith lot's of

funky stuff in it."""

fish = 'whale'
subject = 'something fishy: %s' % fish

user.send_mail(subject, body)

So that’s only 1 line for the actual ‘send my mail’ command. Should you want a different FROM address then you just change the function call to this.

user.send_mail(subject, body, 'notme')

Thus, add parms when you need them or rely on your “Sensible Defaults” from your userconfig.py.

You can build a world of functionality in your “~/.python”. Import and use system wide installed packages in there, test if they are present on your system, etc.


When using scripts under CRON you need to add the PYTHONPATH to the definition like below because CRON does not read your “.bashrc”.

*/1 * * * *  (PYTHONPATH=~/.python; /path/to/your/script.py)

NB: Mind the parenthesis and semicolon on the line above.

Besides the fact that you should watch for name clashes, I can’t think of any other gotcha’s. If you do, then please teach me something and drop me a line 🙂