[Python-Dev] Add __exports__ to modules

Guido van Rossum guido@python.org
Wed, 10 Jan 2001 11:53:16 -0500

> Guido van Rossum wrote:
> > 
> > Please have a look at this SF patch:
> > 
> > http://sourceforge.net/patch/?func=detailpatch&patch_id=102808&group_id=5470
> > 
> > This implements control over which names defined in a module are
> > externally visible: if there's a variable __exports__ in the module,
> > it is a list of identifiers, and any access from outside the module to
> > names not in the list is disallowed.  This affects access using the
> > getattr and setattr protocols (which raise AttributeError for
> > disallowed names), as well as "from M import v" (which raises
> > ImportError).

> Can't we use the existing attribute __all__ (this is currently
> only used for packages) for this kind of thing. As other have already
> remarked: I would rather like to see this attribute being used
> as basis for 'from M import *' rather than enforce the access
> restrictions like the patch suggests.

Yes -- I came up with the same thought.

So here's a plan: somebody please submit a patch that does only one
thing: from...import * looks for __all__ and if it exists, imports
exactly those names.  No changes to dir(), or anything.

> Access control mechanisms should be treated in different ways
> such as wrapping objects using access-control proxies (see mx.Proxy
> for an example of such an implementation) and on-demand only.
> I wouldn't wan't to pay the performance hit for each and every
> lookup in all my Python applications just because someone out
> there feels that "from M import *" has a meaning in life
> apart from being useful in interactive sessions to ease typing ;-)

In the process of looking into Zope internals I've noticed that
proxies are indeed very useful!

I note that the IMPORT opcodes in ceval.c require that the imported
module (as found in sys.modules[name] or returned by __import__()) is
a real module object.  I think this is unnecessary -- at least
IMPORT_FROM should work even if the module is a proxy or some other
thing (I've been known to smuggle class instances into sys.modules :-)
and IMPORT_STAR should work with a non-module at least if it has an
__all__ attribute.

> > I like it.  This has been asked for many times.  Does anybody see a
> > reason why this should *not* be added?
> > 
> > Tim remarked that introducing this will prompt demands for a similar
> > feature on classes and instances, where it will be hard to implement
> > without causing a bit of a slowdown.  It causes a slight slowdown (an
> > extra dictionary lookup for each use of "M.v") even when it is not
> > used, but for accessing module variables that's acceptable.  I'm not
> > so sure about instance variable references.
> Again, I'd rather see these implemented using different
> techniques which are under programmer control and made
> explicit and visible in the program flow. Proxies are ideal
> for these things, since they allow great flexibility while
> still providing reasonable security at Python level.
> I have been using the proxy approach for years now and 
> so far with great success. What's even better is that
> weak references and garbage finalization aids come along with
> it for free.

Agreed.  Which reminds me -- would you mind reviewing Fred's new
version of PEP 205 (weak refs)?

--Guido van Rossum (home page: http://www.python.org/~guido/)