Mr. Brett Cannon
in PyCon2010-USA-Atlanta
45min ◊◊◊ Advanced
Friday 11:45am, Centennial I
categories: core
Since Python 2.3, the ability has existed to customize the import process so that one can support code stored in alternative formats, e.g. zipimport and its support of importing code from a zip file. The aim of this talk is to make sure you understand how the custom import mechanism works and how to write your own custom importers using importlib from Python 3.1.
Import this, that, and the other thing: custom importers
1. If you do not know what __path__ is,
this talk is NOT for you.
Sorry.
2. import this,
that, and the
other thing
Custom importers in Python
Brett Cannon
www.DrBrett.ca
brett@python.org
Slides are sparse, so do listen to what I say.
3. Thanks ...
• Python Software Foundation
• PyCon Financial Aid committee
• Nasuni
• Jesse Noller
4. What the heck is an
importer?
Relevant since Python 2.3
19. Option 3:
importers
http://packages.python.org/importers/
File path abstraction on top of importlib.
Treating as purgatory for importlib
inclusion.
If a lesson here, then it is to use option 2 or 3 depending on your needs.
Rest of talk is about lessons that led to ‘importers’.
20. Using a
zipfile importer
as an example
Assuming use of importlib.
Talking from perspective of using an archive.
31. Need to care
about packages &
modules
some/pkg/name/__init__.py
and
some/pkg/name.py
Care about bytecode if you want.
Notice how many stat calls this takes?
37. importlib.abc.PyLoader
• source_path()
• Might be changing...
• is_package()
• get_data()
Everything in terms of exactly what it takes to import source
38. importlib.abc.PyPycLoader
• source_path()
• is_package()
• get_data()
• source_mtime()
• bytecode_path()
• Might be changing...
This is what is needed to get source w/ bytecode right
39. Reasons to ignore .pyc
• Jython, IronPython couldn’t care less.
• Safe to support, though.
• Another thing to code up.
• Bytecode is just an optimization.
• If you only ship .pyc for code
protection, stop it.
41. Require anchor
point for paths
somewhere/mod.py is too ambiguous
Too hazy as to where a relative path is anchored; archive? Package location?
42. Consider caching
stat calls
Only for stand-alone loaders!
Also consider caching if package or not.
Consider whether storage is read-only, append-only, or read-write.
46. class Module(types.ModuleType):
pass
class Mixin:
def load_module(self, name):
if name in sys.modules:
return super().load_module(name)
# Create a lazy module that will type check.
module = LazyModule(name)
# Set the loader on the module as ModuleType will not.
module.__loader__ = self
# Insert the module into sys.modules.
sys.modules[name] = module
return module
class LazyModule(types.ModuleType):
def __getattribute__(self, attr):
# Remove this __getattribute__ method by re-assigning.
self.__class__ = Module
# Fetch the real loader.
self.__loader__ = super(Mixin, self.__loader__)
# Actually load the module.
self.__loader__.load_module(self.__name__)
# Return the requested attribute.
return getattr(self, attr)
47. ... or you could use
the importers package
http://packages.python.org/importers/