https://www.oreilly.com/library/view/python-cookbook/0596001673/ch14s05.html
https://www.oreilly.com/library/view/python-cookbook/0596001673/ch14s05.html