Dynamic imports + relative imports in Python 3

Discussion in 'Python' started by zildjohn01, Feb 22, 2011.

  1. zildjohn01

    zildjohn01 Guest

    This is a copy-paste of a StackOverflow question. Nobody answered
    there, but I figured I might have better luck here.

    I have a Python 3 project where I'm dynamically importing modules from
    disk, using `imp.load_module`. But, I've run into an problem where
    relative imports fail, when the relative import occurs within a
    dynamically imported module.

    From what I've read, I came to the conclusion that only `__file__`,
    `__path__`, `__package__`, and `__name__` were used by the default
    importer when determining the path of an import. Yet, I've verified
    these in the code below, and it still fails when dynamically imported.
    (It works when imported in the interpreter with an updated `sys.path`)

    # File structure:
    # [root]
    # ├─ __init__.py
    # ├─ board.py
    # └─ test.py

    # Contents of 'board.py':
    import os, sys
    import root # Already imported... just need a reference

    ROOT_DIR = os.path.dirname(root.__file__)
    assert root is sys.modules['root']
    assert root.__package__ is None
    assert root.__name__ == 'root'
    assert root.__file__ == os.path.join(ROOT_DIR, '__init__.py')
    assert not hasattr(root, '__path__')

    xx = object()
    assert xx is sys.modules['root.board'].xx
    assert __package__ is None
    assert __name__ == 'root.board'
    assert __file__ == os.path.join(ROOT_DIR, 'board.py')
    assert not hasattr(sys.modules['root.board'], '__path__')

    assert os.path.isfile(os.path.join(ROOT_DIR, 'test.py'))
    from . import test # ImportError('cannot import name test',)

    But if I hack `sys.path` and reimport the current package just before
    the failed import, it works fine:

    oldroot = root
    del sys.modules['root']
    try:
    sys.path.append(os.path.dirname(ROOT_DIR))
    import root
    finally:
    sys.path.pop(-1)
    from . import test # No error here

    And further, the four golden attributes mentioned above are the same
    in both the new and old packages:

    assert oldroot.__package__ == root.__package__
    assert oldroot.__name__ == root.__name__
    assert oldroot.__file__ == root.__file__
    assert not hasattr(root, '__path__')

    Which means that `__package__`, `__name__`, `__file__`, and `__path__`
    can't be the full story. Are there any other attributes that Python
    uses to locate imports? What am I overlooking that would cause the
    import to fail?
     
    zildjohn01, Feb 22, 2011
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Randall Smith

    Writing apps without using relative imports

    Randall Smith, Dec 3, 2004, in forum: Python
    Replies:
    0
    Views:
    312
    Randall Smith
    Dec 3, 2004
  2. Albert
    Replies:
    4
    Views:
    10,998
    Albert
    Jul 10, 2008
  3. Nicholas

    Relative imports in Python 3.0

    Nicholas, Dec 17, 2008, in forum: Python
    Replies:
    3
    Views:
    716
    Kay Schluehr
    Dec 18, 2008
  4. Victor Hooi
    Replies:
    1
    Views:
    124
    Devin Jeanpierre
    Nov 25, 2013
  5. Replies:
    0
    Views:
    89
Loading...

Share This Page