[Python-Dev] PEP 366 - Relative imports from main modules

Nick Coghlan ncoghlan at gmail.com
Mon Jul 9 12:34:59 CEST 2007


Brett Cannon wrote:
> On 7/8/07, Nick Coghlan <ncoghlan at gmail.com> wrote:
>> As with the current ``__name__`` attribute, setting ``__package__`` will
>> be the responsibility of the PEP 302 loader used to import a module.
>> Loaders which use ``imp.new_module()`` to create the module object will
>> have the new attribute set automatically to
>> ``__name__.rpartition('.')[0]``.
> 
> Is this really the best semantics for this?  Let's say I have
> A/B/__init__.py and A/B/C.py.  With these semantics I would have A.B
> having __package__ be 'A' and A.B.C having 'A.B'.
> 
> While I agree that the A.B.C setting is correct, is the A.B value what
> is truly desired?  Is an __init__ module really to be considered part
> of the above package?  I always viewed the __init__ module as part of
> its own package.  Thus I expected A.B to have __package__ set to
> 'A.B'.

Good point - PEP 328 makes it explicit that __init__.py is treated like 
any other module in the package for purposes of relative imports, so the 
semantics you suggest are the ones required. I hadn't actually thought 
about this case, as it wasn't relevant when the new attribute applied 
only to the main module.

However, those semantics mean that we won't be able to automatically add 
the new attribute inside imp.new_module(), as that function doesn't know 
whether or not the new module is a package.

> Beyond just what I expected, the reason I bring this up is that if
> __package__ had the semantics I am suggesting, it is trivial to
> discover what modules are the package __init__ modules (as
> ``__package__ == __name__``) compared to being a submodule
> (``__package__ and __package__ != __name__``).  As of right now you
> can only do that if you examine __file__ for __init__.py(c), but that
> is highly dependent on how the module was loaded.  It might be nice if
> what kind of module (top-level, package, or submodule) something is
> based on its metadata. 

This part of the argument isn't relevant though, as it's already trivial 
to determine whether or not a module is a package by checking for a 
__path__ attribute. That's what PEP 302 specifies, and it is how the 
relative import machinery currently determines whether to use __name__ 
or __name__.rpartition('.')[0] as the base for relative imports.

Given the above limitations, I propose that we document the new 
attribute as follows:

"If the module global __package__ exists when executing an import 
statement, it is used to determine the base for relative imports, 
instead of the __name__ and __path__ attributes. This attribute may be 
set by the interpreter before a module is executed - whether or not it 
is set automatically in a given module is implementation dependent."

And for the CPython implementation, I propose that we set the new attribute:
   1. When the main module is executed using the -m switch
   2. When a relative import is executed and the attribute is not yet set

This will allow any module which uses relative imports to benefit from 
the micro-optimisation of caching the package name in normal modules 
(regardless of how the module gets loaded), as well as allowing relative 
imports from the main module (which is the main goal of the PEP).

With the way PEP 302 hands off creation of the module and execution of 
its code to the loader objects, I don't see any way to guarantee that 
__package__ will always be set - this seems like a reasonable compromise.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://www.boredomandlaziness.org


More information about the Python-Dev mailing list