This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: Given a module hierarchy string 'a.b.c', add an easy way to import tail module 'c'
Type: enhancement Stage:
Components: Library (Lib) Versions: Python 3.1, Python 2.7
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: georg.brandl, mrts
Priority: normal Keywords: patch

Created on 2008-11-26 11:58 by mrts, last changed 2022-04-11 14:56 by admin. This issue is now closed.

File name Uploaded Description Edit
issue4438.diff mrts, 2008-11-26 14:23 Add 'submodule' argument to __import__()
imp_import_module.diff mrts, 2008-11-28 19:01
Messages (8)
msg76460 - (view) Author: Mart Sõmermaa (mrts) Date: 2008-11-26 11:58
The need to dynamically import module foo given a module name string
'' is quite common.

Quite often, the hack described in is
used (see e.g. the Google code results linked from the issue).

Quoting Brett Cannon from the issue:
"I plan to add a much simpler API to the imp module for people to use
directly so that these abuses don't continue."

Although there are reasonable workarounds, let the current ticket be a
remainder for Brett that his plan is indeed needed.

Perhaps the easiest thing to do would be to add yet another argument,
e.g. 'toplevel', to __import__, such that:

>>> __import__('') # toplevel=True by default
<module 'imprt' from 'imprt/__init__.pyc'>
>>> __import__('', toplevel=False)
<module '' from 'imprt/foo/foo.pyc'>

The latter can currently be achieved by

>>> __import__('', {}, {}, ['foo'])
<module '' from 'imprt/foo/foo.pyc'>

which is cumbersome if the module name is given in a string, resulting
in unnecessarily complex code:

modname = ""
>>> __import__(modname, {}, {}, [modname.rsplit(".", 1)[-1]])
<module '' from 'imprt/foo/foo.pyc'>
msg76466 - (view) Author: Mart Sõmermaa (mrts) Date: 2008-11-26 14:23
Attached is a naive proof-of-concept implementation (that breaks things,
i.e. the real implementation should strive for better
general compatibility), but works as expected:

>>> __import__('', submodule=True)
<module '' from 'imprt/foo/'>

>>> __import__('', submodule=False)   
<module 'imprt' from 'imprt/'>

>>> __import__('')
<module 'imprt' from 'imprt/'>

# Die on unexpected arguments like strings, lists etc to
# avoid confusion
>>> __import__('', submodule='z')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an integer is required
msg76468 - (view) Author: Mart Sõmermaa (mrts) Date: 2008-11-26 15:15
Just a note that `make test` passes:

322 tests OK.
38 tests skipped:
    test_aepack test_al test_applesingle test_bsddb test_bsddb185
    test_bsddb3 test_cd test_cl test_codecmaps_cn test_codecmaps_hk
    test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw test_curses
    test_dbm test_dl test_gl test_imageop test_imgfile test_kqueue
    test_linuxaudiodev test_macos test_macostools test_normalization
    test_ossaudiodev test_pep277 test_py3kwarn test_scriptpackages
    test_socketserver test_startfile test_sunaudiodev test_tcl
    test_timeout test_urllib2net test_urllibnet test_winreg
    test_winsound test_zipfile64
3 skips unexpected on linux2:
    test_tcl test_dbm test_bsddb
msg76497 - (view) Author: Mart Sõmermaa (mrts) Date: 2008-11-27 12:53
Corrections and clarifications:

 * I'd say labeling the patch naive and "breaking things" was misleading
(there was a breakage that resulted from stale files with incorrect
permissions from my previous build of Python 2.6; after a make distclean
all tests passed as described above). The patch is correct and
backwards-compatible in Python level, but it introduces a change in the

 PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel(char *name,
-       PyObject *globals, PyObject *locals, PyObject *fromlist, int level);
+       PyObject *globals, PyObject *locals, PyObject *fromlist,
+       int level, char submodule);

 * The patch was made against Python 2.6 release source.

 * The argument is named 'submodule' instead of 'toplevel' to avoid
confusion with 'level'.
msg76515 - (view) Author: Mart Sõmermaa (mrts) Date: 2008-11-27 20:49
See also
msg76549 - (view) Author: Mart Sõmermaa (mrts) Date: 2008-11-28 18:59
Implement imp.import_module() instead. See
msg76550 - (view) Author: Mart Sõmermaa (mrts) Date: 2008-11-28 19:05
Note that the hack described in should
be disabled once this gets integrated.
msg85071 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-04-01 18:46
This feature is implemented as importlib.import_modules() in 2.7 and
3.1; for earlier versions there is also a backport on PyPI.
Date User Action Args
2022-04-11 14:56:41adminsetgithub: 48688
2009-04-01 18:46:48georg.brandlsetstatus: open -> closed

nosy: + georg.brandl
messages: + msg85071

resolution: out of date
2008-11-28 19:09:09mrtssetcomponents: - Interpreter Core
title: Add an easy way to __import___ submodules -> Given a module hierarchy string 'a.b.c', add an easy way to import tail module 'c'
2008-11-28 19:05:43mrtssetmessages: + msg76550
2008-11-28 19:02:09mrtssetfiles: + imp_import_module.diff
messages: + msg76549
2008-11-27 20:49:07mrtssetmessages: + msg76515
2008-11-27 12:53:31mrtssetmessages: + msg76497
2008-11-26 15:15:53mrtssetmessages: + msg76468
2008-11-26 14:23:58mrtssetfiles: + issue4438.diff
keywords: + patch
messages: + msg76466
2008-11-26 11:58:38mrtscreate