Require __loader__ and __package__ to be set by loaders.
This commit is contained in:
parent
d321dc54a4
commit
04fc727e6f
40
pep-0302.txt
40
pep-0302.txt
|
@ -273,25 +273,33 @@ Specification part 1: The Importer Protocol
|
|||
be a list, but may be empty if __path__ has no further
|
||||
significance to the importer (more on this later).
|
||||
|
||||
- It should add an __loader__ attribute to the module, set to the
|
||||
loader object. This is mostly for introspection, but can be used
|
||||
- The __loader__ attribute must be set to the loader object.
|
||||
This is mostly for introspection and reloading, but can be used
|
||||
for importer-specific extras, for example getting data associated
|
||||
with an importer.
|
||||
|
||||
- The __package__ attribute [10] must be set.
|
||||
|
||||
If the module is a Python module (as opposed to a built-in module or
|
||||
a dynamically loaded extension), it should execute the module's code
|
||||
in the module's global name space (module.__dict__).
|
||||
|
||||
Here is a minimal pattern for a load_module() method:
|
||||
|
||||
# Consider using importlib.util.module_for_loader() to handle
|
||||
# most of these details for you.
|
||||
def load_module(self, fullname):
|
||||
ispkg, code = self._get_code(fullname)
|
||||
code = self.get_code(fullname)
|
||||
ispkg = self.is_package(fullname)
|
||||
mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
|
||||
mod.__file__ = "<%s>" % self.__class__.__name__
|
||||
mod.__loader__ = self
|
||||
if ispkg:
|
||||
mod.__path__ = []
|
||||
exec code in mod.__dict__
|
||||
mod.__package__ = fullname
|
||||
else:
|
||||
mod.__package__ = fullname.rpartition('.')[0]
|
||||
exec(code, mod.__dict__)
|
||||
return mod
|
||||
|
||||
|
||||
|
@ -485,24 +493,9 @@ Open Issues
|
|||
importer object, zipimport also adds an attribute "__loader__"
|
||||
to the module, containing the zipimport object used to load the
|
||||
module. If such an approach is used, it is important that client
|
||||
code takes care not to break if the get_data method (or the
|
||||
__loader__ attribute) is not available, so it is not clear that
|
||||
this approach offers a general answer to the problem.
|
||||
|
||||
Requiring loaders to set the module's __loader__ attribute means
|
||||
that the loader will not get thrown away once the load is complete.
|
||||
This increases memory usage, and stops loaders from being
|
||||
lightweight, "throwaway" objects. As loader objects are not
|
||||
required to offer any useful functionality (any such functionality,
|
||||
such as the zipimport get_data() method mentioned above, is
|
||||
optional) it is not clear that the __loader__ attribute will be
|
||||
helpful, in practice.
|
||||
|
||||
On the other hand, finder objects are mostly permanent, as they
|
||||
live or are kept alive on sys.meta_path, sys.path_importer_cache, so
|
||||
for a loader to keep a reference to the importer costs us nothing
|
||||
extra. Whether loaders will ever need to carry so much independent
|
||||
state for this to become a real issue is questionable.
|
||||
code takes care not to break if the get_data method is not available,
|
||||
so it is not clear that this approach offers a general answer to the
|
||||
problem.
|
||||
|
||||
It was suggested on python-dev that it would be useful to be able to
|
||||
receive a list of available modules from an importer and/or a list
|
||||
|
@ -586,6 +579,9 @@ References and Footnotes
|
|||
[9] PEP 338: Executing modules as scripts
|
||||
http://www.python.org/dev/peps/pep-0338/
|
||||
|
||||
[10] PEP 366: Main module explicit relative imports
|
||||
http://www.python.org/dev/peps/pep-0366/
|
||||
|
||||
|
||||
Copyright
|
||||
|
||||
|
|
Loading…
Reference in New Issue