[Solved] trying to make paths work – attempted relative import beyond top-level package

I can’t make this work..

My structure is:

program_name/

  __init__.py
  setup.py

  src/
    __init__.py

    Process/
        __init__.py
        thefile.py

  tests/
     __init__.py
     thetest.py

thetest.py:

from ..src.Process.thefile.py import sth

Running: pytest ./tests/thetest.py from program_name gives :

ValueError: attempted relative import beyond top-level package

I tried also other approaches but i am receiving various errors.

But I would expect for the above to work.

Enquirer: George

||

Solution #1:

ValueError: Attempted relative import in non-package

States that you’re trying to use relative import in the module, which are to be used for packages i.e. to make it a package add __init__.py and call the thetest.py from some file outside the package.
Directly running thetest.py from interpreter won’t work.

Relative imports require that the module which uses them is being
imported itself either as package module.


Suggestion 1:

The current tests directory has a __init__.py file but that doesn’t allow you to run it as a module (via shell) – to make your current (relative) import work, you need to import it in an external (to package) file/module – let’s create a main.py (can name it anything you like):

    main.py
    program_name/
      __init__.py
      setup.py
      src/
        __init__.py
        Process/
            __init__.py
            thefile.py
      tests/
         __init__.py
         thetest.py

src/Process/thefile.py:

s = 'Hello world'

tests/thetest.py:

from ..src.Process.thefile import s

print s

main.py:

from program_name.tests.thetest import s

Executing main.py:

[[email protected] ~]$ python main.py 
Hello world

Suggestion 2:

Execute the file just above root dir i.e. one level up the program_name/ , in the following fashion:

[[email protected] ~]$ python -m program_name.tests.thetest
Hell World

P.S. relative imports are for packages, not modules.

Respondent: George

Solution #2:

Just solved a similar problem with a lot of googling.
Here’s two solutions without changing the existing file structor:

1

The way to import module from parent folder from ..src.Process.thefile.py import sth is called “relative import”.

It’s only supported when launching as a package from the top-level package. In your case, that is launching command line from the directory which contains program_name/ and type (for win environment)

python -m program_name.tests.thetest

2

Otherwise — when trying to run a script alone or from a non top-level package —
you could manually add directory to the PYTHONPATH at run time.

import sys
from os import path
sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
from src.Process.thefile import s

Try the first one first see if it’s compatiable with the pytest framework. Otherwise the second one should always solve the problem.

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

Respondent: Nabeel Ahmed

Solution #3:

When importing a file, Python only searches the current directory, the directory that the entry-point script is running from.
you can use sys.path to include different locations

import sys
sys.path.insert(0, '/path/to/application/app/folder')

import thefile
Respondent: Yibo

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Leave a Reply

Your email address will not be published.