Find out which module a class came from

Steve D'Aprano steve+python at pearwood.info
Fri Apr 7 20:48:59 EDT 2017


On Sat, 8 Apr 2017 06:24 am, Tobiah wrote:

> I was viewing the python source for a program at work and
> came across a class name that I knew my company had written:
> 
> import mycmp1
> import mycmp2
> import mycmp3
> import mycmp4
> import mycmp5
> 
> foo = FooClass()
> 
> 
> So I knew that FooClass was defined in one of those imports,

No you don't. You know the opposite: FooClass must be defined *locally* in
the current file, because the name isn't fully qualified.

(Well, I say "must" but technically that's not *quite* true... it is
possible that one of the modules mycmp1 etc. could inject FooClass into
your module, but that's pretty unlikely.)

If you have:

from mycmp1 import FooClass
from mycmp2 import FooClass
# etc.

foo = FooClass

then the last import wins. If you have wild-card imports:

from mycmp1 import *
from mycmp2 import *
# etc.

then (1) your dev team should be stoned to death with ripe figs (so it takes
longer), and (2) the same rule applies again: the last module importing a
FooClass will override any previous imports of the same name.


> but 
> I thought it would be tedious to track down the location of all
> of those modules (is module.__file___ the best way) 

I don't know about "best". Actually having a well-structured code base is
probably best. But if you are stuck with a tangled mess, then
module.__file__ is probably your least-worst option.


> and scan them 
> for the class definition.  Is there a better way to find the
> definition of FooClass()?

Keep in mind that a sufficiently perverted and incompetent programmer can
*accidentally* duplicate the trickiest obfuscation used by intentionally
malicious programmers, so there is no guarantee. And if you are trying to
analyse malware, or code written by somebody intentionally obfuscating the
source so as to guarantee job-security, all bets are off.

But for merely ordinary obfuscation caused by poor design, your best bet is
probably to inspect Foo.__module__.

You can also try:

inspect.getsource(FooClass)
inspect.getsourcefile(FooClass)



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list