How to do relative imports in Python?

前端 未结 15 2805
情深已故
情深已故 2020-11-21 04:47

Imagine this directory structure:

app/
   __init__.py
   sub1/
      __init__.py
      mod1.py
   sub2/
      __init__.py
      mod2.py

I\'

相关标签:
15条回答
  • 2020-11-21 05:32

    This is unfortunately a sys.path hack, but it works quite well.

    I encountered this problem with another layer: I already had a module of the specified name, but it was the wrong module.

    what I wanted to do was the following (the module I was working from was module3):

    mymodule\
       __init__.py
       mymodule1\
          __init__.py
          mymodule1_1
       mymodule2\
          __init__.py
          mymodule2_1
    
    
    import mymodule.mymodule1.mymodule1_1  
    

    Note that I have already installed mymodule, but in my installation I do not have "mymodule1"

    and I would get an ImportError because it was trying to import from my installed modules.

    I tried to do a sys.path.append, and that didn't work. What did work was a sys.path.insert

    if __name__ == '__main__':
        sys.path.insert(0, '../..')
    

    So kind of a hack, but got it all to work! So keep in mind, if you want your decision to override other paths then you need to use sys.path.insert(0, pathname) to get it to work! This was a very frustrating sticking point for me, allot of people say to use the "append" function to sys.path, but that doesn't work if you already have a module defined (I find it very strange behavior)

    0 讨论(0)
  • 2020-11-21 05:36

    Here is the solution which works for me:

    I do the relative imports as from ..sub2 import mod2 and then, if I want to run mod1.py then I go to the parent directory of app and run the module using the python -m switch as python -m app.sub1.mod1.

    The real reason why this problem occurs with relative imports, is that relative imports works by taking the __name__ property of the module. If the module is being directly run, then __name__ is set to __main__ and it doesn't contain any information about package structure. And, thats why python complains about the relative import in non-package error.

    So, by using the -m switch you provide the package structure information to python, through which it can resolve the relative imports successfully.

    I have encountered this problem many times while doing relative imports. And, after reading all the previous answers, I was still not able to figure out how to solve it, in a clean way, without needing to put boilerplate code in all files. (Though some of the comments were really helpful, thanks to @ncoghlan and @XiongChiamiov)

    Hope this helps someone who is fighting with relative imports problem, because going through PEP is really not fun.

    0 讨论(0)
  • 2020-11-21 05:37

    From Python doc,

    In Python 2.5, you can switch import‘s behaviour to absolute imports using a from __future__ import absolute_import directive. This absolute- import behaviour will become the default in a future version (probably Python 2.7). Once absolute imports are the default, import string will always find the standard library’s version. It’s suggested that users should begin using absolute imports as much as possible, so it’s preferable to begin writing from pkg import string in your code

    0 讨论(0)
  • 2020-11-21 05:40

    Everyone seems to want to tell you what you should be doing rather than just answering the question.

    The problem is that you're running the module as '__main__' by passing the mod1.py as an argument to the interpreter.

    From PEP 328:

    Relative imports use a module's __name__ attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to '__main__') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.

    In Python 2.6, they're adding the ability to reference modules relative to the main module. PEP 366 describes the change.

    Update: According to Nick Coghlan, the recommended alternative is to run the module inside the package using the -m switch.

    0 讨论(0)
  • 2020-11-21 05:40

    Let me just put this here for my own reference. I know that it is not good Python code, but I needed a script for a project I was working on and I wanted to put the script in a scripts directory.

    import os.path
    import sys
    sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
    
    0 讨论(0)
  • 2020-11-21 05:41

    Take a look at http://docs.python.org/whatsnew/2.5.html#pep-328-absolute-and-relative-imports. You could do

    from .mod1 import stuff
    
    0 讨论(0)
提交回复
热议问题