[PEAK] imports (Re: Package organization)
Phillip J. Eby
pje at telecommunity.com
Thu Dec 4 09:13:18 EST 2003
At 11:13 AM 12/4/03 +0200, alexander smishlajev wrote:
>i would prefer peak.api (or whatever name is chosen for such module) to
>export only core - no primitives, no frameworks.
>
>however, this issue does not affect me or my colleagues since the coding
>policy in our company is to avoid 'from module import *' in favor of
>'import module' (better) or 'from module import symbol1, symbol2'. so we
>never do 'from peak.api import *'.
I'm confused, on two points. First, why do you care what it exports if
you're not going to use import *? Second, if it doesn't export the
primitives (especiall NOT_GIVEN and NOT_FOUND), where will you get them from?
>by the way, i would like to mention some problems i discovered in
>peak.util.imports.
>
>first, there is inconsistence between LazyModule and _loadAndRunHooks: if
>any of the hooks fail, _loadAndRunHooks still believes that the module is
>imported (by disabling all postLoadHooks for that module), but LazyModule
>thinks that the module is *not* imported, and tries to _loadAndRunHooks
>again upon the next attribute access. this leads to AlreadyRead exception.
True. And then the module concludes it's *still* not
imported. Unfortunately I don't think there's much I can do about this,
except maybe allow the hooks to be run more than once, which I don't really
like. I suppose I could wipe the module's contents. Or, I suppose I could
change things so that warnings were issued for errors in the hooks, and
things just proceeded forward. Or maybe I could accumulate all the errors
and issue a single error for them. Sigh. None of these options seems
really appealing. It would be better if hooks didn't raise errors, and in
fact the 'whenImported()' docs say:
"The hook should not raise any exceptions, or it may prevent later
hooks from running."
Maybe I should just change it to say, "or it may completely hose the module
and your entire application." :)
>second, _loadAndRunHooks may be executed before the module code. if any
>of the hooks refer to an attribute of the module being imported, it fail:
>
>[snip traceback]
>
>this makes lazy modules incompatible with non-basic import mechanisms,
>like imputil. essentially, they do
>
> module = imp.new_module(fqname)
> exec code in module.__dict__
>
>this launches _loadAndRunHooks upon access to module.__dict__ (or any
>special import attribute, like '__importer__' or '__ispkg__'), when the
>module code has not been executed, and always leads to the problem shown
>in above example.
I'm a little puzzled as to how they get to that point, unless
imp.new_module is returning the module from sys.modules. I suppose I could
make the __getattribute__ avoid loading on access to attributes that begin
and end with double underscores. But, it's possible that for some
attributes, this would be a bad thing. For example, a module's __conform__
method would be accessed by adapt(). Without a comprehensive list of which
attributes to ignore, it would be unlikely to be correct in all cases. I
could add such a list of attributes known to be read by importers, I suppose.
What I find confusing here, though, is that an importer shouldn't be
touching such attributes except *during* the reload() call, and during the
reload() call the __getattribute__ method has been restored to its normal
value! So, I don't understand how you're getting this problem, even though
I see that it's a problem.
>for my application packaging, i found a workaround to overcome peak module
>lazyness, so these problems do not bite me much yet.
Just for my information, could you tell me what that is?
>i just think: do lazy core modules make sense at all? i.e. how common is
>it for core modules to not instantiate at the very start of the application?
The PEAK core itself uses 'from peak.api import *', so the core itself is
unable to boot without lazy loading. It could be changed to use direct
imports from other packages' modules, but it would be a fair amount of
work. I wanted to shield packages from having to know each others'
internal organization as much as possible. Indeed, the lazy loading was
something I originally created in order to deal with the circularities of
booting the core.
More information about the PEAK
mailing list