How to fix “Attempted relative import in non-package” even with __init__.py

后端 未结 19 2590
予麋鹿
予麋鹿 2020-11-21 21:51

I\'m trying to follow PEP 328, with the following directory structure:

pkg/
  __init__.py
  components/
    core.py
    __init__.py
  tests/
    core_test.py         


        
相关标签:
19条回答
  • 2020-11-21 22:46

    Issue is with your testing method,

    you tried python core_test.py

    then you will get this error ValueError: Attempted relative import in non-package

    Reason: you are testing your packaging from non-package source.

    so test your module from package source.

    if this is your project structure,

    pkg/
      __init__.py
      components/
        core.py
        __init__.py
      tests/
        core_test.py
        __init__.py
    

    cd pkg

    python -m tests.core_test # dont use .py
    

    or from outside pkg/

    python -m pkg.tests.core_test
    

    single . if you want to import from folder in same directory . for each step back add one more.

    hi/
      hello.py
    how.py
    

    in how.py

    from .hi import hello
    

    incase if you want to import how from hello.py

    from .. import how
    
    0 讨论(0)
  • 2020-11-21 22:47

    My quick-fix is to add the directory to the path:

    import sys
    sys.path.insert(0, '../components/')
    
    0 讨论(0)
  • 2020-11-21 22:48

    Try this

    import components
    from components import *
    
    0 讨论(0)
  • 2020-11-21 22:52

    As Paolo said, we have 2 invocation methods:

    1) python -m tests.core_test
    2) python tests/core_test.py
    

    One difference between them is sys.path[0] string. Since the interpret will search sys.path when doing import, we can do with tests/core_test.py:

    if __name__ == '__main__':
        import sys
        from pathlib import Path
        sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
        from components import core
        <other stuff>
    

    And more after this, we can run core_test.py with other methods:

    cd tests
    python core_test.py
    python -m core_test
    ...
    

    Note, py36 tested only.

    0 讨论(0)
  • 2020-11-21 22:53

    Yes. You're not using it as a package.

    python -m pkg.tests.core_test
    
    0 讨论(0)
  • 2020-11-21 22:55

    To elaborate on Ignacio Vazquez-Abrams's answer:

    The Python import mechanism works relative to the __name__ of the current file. When you execute a file directly, it doesn't have its usual name, but has "__main__" as its name instead. So relative imports don't work.

    You can, as Igancio suggested, execute it using the -m option. If you have a part of your package that is meant to be run as a script, you can also use the __package__ attribute to tell that file what name it's supposed to have in the package hierarchy.

    See http://www.python.org/dev/peps/pep-0366/ for details.

    0 讨论(0)
提交回复
热议问题