trying to make paths work - attempted relative imp

2020-08-22 07:28发布

问题:

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.

回答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:

[nahmed@localhost ~]$ 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:

[nahmed@localhost ~]$ python -m program_name.tests.thetest
Hell World

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



回答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)



回答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


标签: python pytest