I have found that python-dotenv helps solve this issue pretty effectively. Your project structure ends up changing slightly, but the code in your notebook is a bit simpler and consistent across notebooks.
For your project, do a little install.
pipenv install python-dotenv
Then, project changes to:
+-- .env (this can be empty)
+-- ipynb
¦ +-- 20170609-Examine_Database_Requirements.ipynb
¦ +-- 20170609-Initial_Database_Connection.ipynb
+-- lib
+-- __init__.py
+-- postgres.py
And finally, your import changes to:
import os
import sys
from dotenv import find_dotenv
sys.path.append(os.path.dirname(find_dotenv()))
A +1 for this package is that your notebooks can be several directories deep. python-dotenv will find the closest one in a parent directory and use it. A +2 for this approach is that jupyter will load environment variables from the .env file on startup. Double whammy.