How to accomplish relative import in python

前端 未结 6 1188
隐瞒了意图╮
隐瞒了意图╮ 2020-12-01 10:38
stuff/
    __init__.py
    mylib.py
    Foo/
        __init__.py
        main.py
        foo/
            __init__.py
            script.py

s

相关标签:
6条回答
  • 2020-12-01 11:10

    I'm running Python 3.4.2 on Windows 7 and tore my hair out over this.

    When running either of these:

    python -m unittest python -m unittest discover

    ...I would get the 'Attempted relative import beyond toplevel package' error.

    For me, the solution was dropping the ".." in my [test_stock.py]. The line was: from ..stock import Stock

    Changed it to: from stock import Stock

    .. and it works.

    Folder structure:

    C:\
      |
      +-- stock_alerter
                 |
                 +-- __init__.py
                 +-- stock.py
                 |
                 \-- tests
                       |
                       +-- __init__.py
                       \-- test_stock.py
    
    0 讨论(0)
  • 2020-12-01 11:13

    though as long "stuff" is not in your python PATH you got no choice than adding the path.

    If you know the level of your script.py from stuff you can do for example:

    import sys
    import os
    sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
    
    0 讨论(0)
  • 2020-12-01 11:21

    import ..foo..stuff.mylib should be ok

    EDIT took off the extension

    0 讨论(0)
  • 2020-12-01 11:21

    From the PEP it appears that you cannot use a relative import to import a file that is not packaged.

    So you would need to add a __init__.py to stuff and change your imports to something like from .mylib import *

    However, the PEP seems to make no allowance to keep mylib packaged up in a module. So you might be required to change how you call your library functions.

    Another alternative is to move mylib into a subpackage and import it as from .libpackage import mylib

    0 讨论(0)
  • 2020-12-01 11:22

    After fiddling with it a bit more, I realized how to set it up, and for the sake of specificity I won't use foo bar names. My project directory is set up as...

    tools/
        core/
            object_editor/
                # files that need to use ntlib.py
                editor.py # see example at bottom
                __init__.py
            state_editor/
                # files that need to use ntlib.py
                __init__.py
            ntlib.py
            __init__.py # core is the top level package
        LICENSE
        state_editor.py # equivalent to main.py for the state editor
        object_editor.py # equivalent to main.py for the object editor
    

    A line in object_editor.py looks like...

    from core.object_editor import editor
    

    A line in editor.py looks like...

    from .. import ntlib
    

    or alternatively

    from core import ntlib
    

    The key is that in the example I gave in the question, the "main" script was being run from within the package. Once I moved it out, created a specific package (core), and moved the library I wanted the editors to share (ntlib) into that package, everything was hunky-dory.

    0 讨论(0)
  • 2020-12-01 11:25

    If you're on Linux or perhaps a similar *nix, you can hack this with symlinks.

    stuff/
        mylib.py
        foo.py // equivalent of main.py in above
        foo/
            script.py
            mylib.py  ->  ../mylib.py
        foo2/
            script2.py
            mylib.py  ->  ../mylib.py
    
    

    This is likely not a good pattern to follow.

    In my case I opted for it because I had multiple executables dependent on the same library that needed to be put into separate directories.

    Implementation of new executable tests shouldn't require the test writer to have a deep understanding of python imports.

    tests/
        common/
            commonlib.py
        test1/
            executable1.py
            executable2.py
            commonlib.py -> ../common/commonlib.py
        test2/
            executable1.py
            executable2.py
            commonlib.py -> ../common/commonlib.py
    
    
    
    0 讨论(0)
提交回复
热议问题