ну, в данном случае с TypeError это, по-моему, очевидно. Естественно, функция ожидает либо str либо unicode объект, и при указании числа, скажем, или того же None будет TypeError. Еще пример:
>>> abs(-1)
1
>>> abs('1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bad operand type for abs(): 'str'
>>>
Функция abs возвращает модуль (абсолютное значение) числа, вы ж не будете туда передавать строку и ожидать что функция что-то вернет правильно?
Если есть затруднения с определением типа аргумента, который вы будете передавать в функцию пользуйтесь, скажем assert:
>>> ...
>>> path = None
>>> assert type(path) == type('') or type(path) == type(u'')
>>> os.path.exists(path)
>>> False
>>> ...
Очень помогает в дебаге кода, так как вы заранее указываете интерпретатору, что значение path обязательно должно быть строкой поскольку на этапе тестирования вам обязательно, если такое случится выпрыгнет AssertionError, и вы сможете узнать откуда взялся этот неверный аргумент.