[Python-Dev] Breaking undocumented API

Steven D'Aprano steve at pearwood.info
Thu Nov 11 19:16:16 CET 2010


Nick Coghlan wrote:

> My personal opinion is that we should be trying to get the standard
> library to the point where __all__ definitions are unnecessary - if a
> name isn't in __all__, it should start with an underscore (and if that
> is true, then the __all__ definition becomes effectively redundant).

You don't *need* to define __all__ -- if you don't, import * will import 
everything that doesn't start with a leading underscore. __all__ is only 
useful when you want more control over what is or isn't imported. If you 
don't need that control, just don't define __all__, and the problem is 
solved.


> That way, all sources of information (docs, dir(), help(), import *)
> give the same answer as to what constitutes the public API.


I disagree with the underlying assumption that import * need necessarily 
import the entire public API. That's not how I use it in my modules, and 
the option should be available to std library modules as well.

When I create a module, I distinguish between three categories of functions:

* private, which start with an underscore;
* the core public API, which is listed in __all__; and
* support/helper functions, which are not part of the core functionality 
of the module but are public.

If you import * you will get just the core functions. If you want the 
support functions, you need to use the fully qualified module.name, or 
otherwise import them yourself.

This division of public functions into first and second class API 
functions is a deliberate design choice on my part. I expect the core 
functionality to be fully documented. Helper and support functions may 
not be -- there should be some docs, but doing so is a lower priority.

The support functions are public, and available for use, if you go 
looking for them, but I neither encourage nor discourage users from 
doing so.

I don't see any reason that the standard library should not be permitted 
to use the same convention.


Another couple of objections to getting rid of __all__:

If you're proxying modules or built-ins, you may not be able to use a 
_private name, but you may not want import * to pick up your proxies.

I find it annoying to see this:

import module as _module
_module.func()

(instead of import module and merely leaving module out of __all__)

I accept that some standard library authors may choose this convention, 
but I don't want to see it become mandatory.



-- 
Steven


More information about the Python-Dev mailing list