0

I have the following project structure (using python 3.6):

Project
|  scripts
|  |  module.py
|  tests
|  |  test.py

module.py contains a class named Class1.

test.py has the following code:

from .. scripts.module.py import Class1

However, when I run test.py, I get the following error:

ValueError: attempted relative import beyond top-level package

How do I fix this? Why is the relative import not working?

This post is probably going to be marked as a duplicate, but I either cannot understand the posts that I have seen so far, or the posts do not reflect my situation.

Edit: I looked at some python Github repositories, and they in their test code, they all do something like import scripts.module. How does this work?? Do I need an additional file to be able to connect my project like this?

Here are the Github repositories that I looked at. What I am talking about is located in the tests folder: https://github.com/AtsushiSakai/PythonRobotics and https://github.com/nbedos/termtosvg.

Frank
  • 414
  • 4
  • 15
  • See [this answer](https://stackoverflow.com/a/45874916/6221024) – Dillon Davis Jul 14 '18 at 02:56
  • I tried that and it didn't work. I'm assuming that you would have to get rid of the '..' in the line of code I had in my answer, but it didn't work with/without the '..'. – Frank Jul 14 '18 at 02:59
  • Try `from Project.scripts import module` – Dillon Davis Jul 14 '18 at 03:01
  • Oh wow, that worked. Thanks! However, is there a better way to do this? Writing the import sys code at the beginning of every single test program seems unnecessary. – Frank Jul 14 '18 at 03:05
  • Not to mention the editor I'm using is underlining the import line even though it works :/. – Frank Jul 14 '18 at 03:06
  • You shouldn't need both the `sys.path.append...` and `from Project.scripts...`, only the latter. Try removing the import sys and path append, to see if it still works. – Dillon Davis Jul 14 '18 at 03:09
  • Doesn't work. I tried `from Project.scripts...` and `from ... Project.scripts...` and neither of them work. – Frank Jul 14 '18 at 03:11
  • Then I believe the best you can do is make an testing module, and within that module import sys, append to the path, import your scripts, and then place that module in the tests directory and import that. – Dillon Davis Jul 14 '18 at 03:13
  • Hmm.. okay. I thought having a package for tests and one for other stuff would be pretty standard and that python would have some good way to handle it... Is there another project structure you would suggest? Thanks anyways for the help! – Frank Jul 14 '18 at 03:20

1 Answers1

1

Answering my own question here:

Apparently, when running a python script, it is impossible to import anything above the directory where the script is located without modifying sys.path (Source, see case 4). The package the script being run is in is treated as the top-level module. You can't go above that if that's the script being run.

Of course, there are workarounds:

Solution:

  1. Modify sys.path. Here's the best method of doing this I found (given the file directory structure I had above, you might have a different amount of periods):

    import sys.path
    sys.path.append('.')
    
    from scripts.module import Class1
    
  2. Run the module from a script above. For example, I would change my file directory to:

    Project
    |  main.py
    |  scripts
    |  |  module.py
    |  tests
    |  |  test.py
    

    In main.py, I would put:

    import tests.test.py
    

    I could have the following in test.py, and it would still work out:

    from scripts.module import Class1
    
  3. Have the same thing in test.py as #2 but instead run it from command prompt:

    cd ...\Project
    python
    >>> import tests.test
    >>> # do what you need
    
Frank
  • 414
  • 4
  • 15