Since PEP 489 (Python 3.5.0b1), loaders now support create_module/exec_module. For modules which don't use the PEP's new multi-phase init mechanism (which is most of them, currently), load_module() does all the work and exec_module is a no-op.
So, this issue can be closed.
Python 3.5.0b2+ (default, Jun 2 2015, 20:48:59)
[GCC 4.9.2 20150212 (Red Hat 4.9.2-6)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from importlib.util import find_spec, module_from_spec
>>> spec = find_spec('math')
>>> spec
ModuleSpec(name='math', loader=<_frozen_importlib_external.ExtensionFileLoader object at 0x7f7d67b51588>, origin='/home/petr/dev/cpython/__installed__/lib/python3.5/lib-dynload/math.cpython-35m-x86_64-linux-gnu.so')
>>> math = module_from_spec(spec)
>>> math
<module 'math' from '/home/petr/dev/cpython/__installed__/lib/python3.5/lib-dynload/math.cpython-35m-x86_64-linux-gnu.so'>
>>> dir(math)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
>>> spec.loader.exec_module(math)
>>> spec.loader.load_module(spec.name)
<module 'math' from '/home/petr/dev/cpython/__installed__/lib/python3.5/lib-dynload/math.cpython-35m-x86_64-linux-gnu.so'>
>>> dir(math)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
The "array" module implements multi-phase init, so create_module/exec_module work more like with Python modules:
>>> spec = find_spec('array')
>>> spec
ModuleSpec(name='array', loader=<_frozen_importlib_external.ExtensionFileLoader object at 0x7f7d67b51f60>, origin='/home/petr/dev/cpython/__installed__/lib/python3.5/lib-dynload/array.cpython-35m-x86_64-linux-gnu.so')
>>> array = module_from_spec(spec)
>>> array
<module 'array' from '/home/petr/dev/cpython/__installed__/lib/python3.5/lib-dynload/array.cpython-35m-x86_64-linux-gnu.so'>
>>> dir(array)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_array_reconstructor']
>>> spec.loader.exec_module(array)
>>> dir(array)
['ArrayType', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_array_reconstructor', 'array', 'typecodes']
(Module methods [like _array_reconstructor here] and __doc__ are initialized in load_module -- an implementation detail related to reusing the existing C structure for defining extension modules.) |