Question

I have a python source file with a class defined in it, and a class from another module imported into it. Essentially, this structure:

from parent import SuperClass
from other import ClassA

class ClassB(SuperClass):
    def __init__(self): pass

What I want to do is look in this module for all the classes defined in there, and only to find ClassB (and to overlook ClassA). Both ClassA and ClassB extend SuperClass.

The reason for this is that I have a directory of plugins which are loaded at runtime, and I get a full list of the plugin classes by introspecting on each .py file and loading the classes which extend SuperClass. In this particular case, ClassB uses the plugin ClassA to do some work for it, so is dependent upon it (ClassA, meanwhile, is not dependent on ClassB). The problem is that when I load the plugins from the directory, I get 2 instances of ClassA, as it gets one from ClassA's file, and one from ClassB's file.

For packages there is the approach:

__all__ = ['module_a', 'module-b']

to explicitly list the modules that you can import, but this lives in the __init__.py file, and each of the plugins is a .py file not a directory in its own right.

The question, then, is: can I limit access to the classes in a .py file, or do I have to make each one of them a directory with its own init file? Or, is there some other clever way that I could distinguish between these two classes?

Était-ce utile?

La solution

You meant "for packages there is the approach...". Actually, that works for every module (__init__.py is a module, just with special semantics). Use __all__ inside the plugin modules and that's it.

But remember: __all__ only limits what you import using from xxxx import *; you can still access the rest of the module, and there's no way to avoid that using the standard Python import mechanism.

If you're using some kind of active introspection technique (eg. exploring the namespace in the module and then importing classes from it), you could check if the class comes from the same file as the module itself.

You could also implement your own import mechanism (using importlib, for example), but that may be overkill...

Edit: for the "check if the class come from the same module":

Say that I have two modules, mod1.py:

class A(object):
    pass

and mod2.py:

from mod1 import A

class B(object):
    pass

Now, if I do:

from mod2 import *

I've imported both A and B. But...

>>> A
<class 'mod1.A'>
>>> B
<class 'mod2.B'>

as you see, the classes carry information about where did they originate. And actually you can check it right away:

>>> A.__module__
'mod1'
>>> B.__module__
'mod2'

Using that information you can discriminate them easily.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top