It sounds like a dead code problem. You've got two options:
Code coverage tools
This involves using a tool that can detect when a particular piece of code is actually run. This is known as code instrumentation.
For this to work, you must run the code through an extensive set of tests, ensuring that every part of the code that could be run in a real deployment scenario is actually run. The code coverage tool will then tell you what's "left over".
Coverage.py is one I've used before.
The problem here is that if you don't already have that extensive test suite, you're going to have to right one.
Static Analysis
Static analysis involves inspecting of the source code in an attempt to infer runtime problems that might occur.
The issue with static analysis in a dynamic language like python, that it is very hard to determine what code is being run/used just from the source code. Some things are easy to spot statically (undefined variables for example, although there are caveats to even that) but some are less so. Take the following example:
class A:
value = 1
class B:
value = 2
l = [A(), B()]
print l[0].value
Without actually running the code, the static analyser is going to have a hard time working out that B.value
is never used, and impossible is the list index came from user input.
In python, there are not many options for static analysis, but there are one or two tools out there. Vulture is one example, but as is say, it's not going to be very correct.