60

I have gone through many Python relative import questions but I can't understand the issue/get it to work.

My directory structure is:

Driver.py

A/
      Account.py
      __init__.py

B/
      Test.py
      __init__.py

Driver.py

from B import Test

Account.py

class Account:
def __init__(self):
    self.money = 0

Test.py

from ..A import Account

When I try to run:

python Driver.py

I get the error

Traceback (most recent call last):

from B import Test

File "B/Test.py", line 1, in <module> from ..A import Account

ValueError: Attempted relative import beyond toplevel package
double-beep
  • 4,567
  • 13
  • 30
  • 40
Joshua
  • 1,416
  • 2
  • 22
  • 31
  • 5
    You really should mention your Python version when asking about features which have changed radically between versions (relative imports, Unicode, and a few others). Sometimes people will be able to guess based on the specific error you got, or how you wrote your code, but you shouldn't count on people guessing right. – abarnert Feb 15 '13 at 00:42

3 Answers3

37

This is happening because A and B are independent, unrelated, packages as far as Python is concerned.

Create a __init__.py in the same directory as Driver.py and everything should work as expected.

David Wolever
  • 139,281
  • 83
  • 327
  • 490
  • 1
    Thanks! Can you explain the __init__.py files a little bit? I have not understood explanations found online. I come from a c++ background, so I am used to just giving the path for includes and such – Joshua Feb 15 '13 at 14:04
  • 14
    It's a bit hand-wavy, but basically: putting a `__init__.py` file in a directory means "in this directory, all of the `.py` files, and all of the subdirectories which contain a `__init__.py` file, are part of the same package". – David Wolever Feb 15 '13 at 15:56
  • All he needs if from A import Account in driver.py. Adding the extra init.py and using a relative import is a bit awkward and pollutes the toplevel. – Wyrmwood Nov 10 '14 at 19:49
  • 2
    This solution doesn't work for me using Python 2.7.14. I assume the solution is for Python 3.x? Is there a python2 solution for those forced to work in legacy systems? – retsigam Apr 14 '18 at 23:40
  • @retsigam This works for both Python 2 & Python 3. In fact, this syntax was created for Python 2.3 or 2.4 or something like that (I forget the release time). – Mike Williamson Jun 27 '18 at 00:58
  • While @DavidWolever is 100% right, the [preferred style](https://www.python.org/dev/peps/pep-0008/?#imports) is to use a full import once you've done those `__init__.py` tricks. E.g., `from .A import Account`. – Mike Williamson Jun 27 '18 at 01:02
  • 49
    I created an `__init__.py` and I'm still getting the same error. I'm on Python 3.7. What gives? – Jared Nielsen Feb 01 '19 at 02:44
  • I use 3.6.8 and I need `Test.py` to read `from A import account`. Then, I can call `Driver.py` from its containing directory. – smcs Nov 05 '19 at 18:18
  • If nothing here is working for you, I recommend reading the accepted answer to this question: https://stackoverflow.com/questions/14132789/relative-imports-for-the-billionth-time. It explains how relative imports work and helped me understand at least why my imports weren't working. – Rob Streeting Feb 17 '21 at 11:01
6

In my case adding __init__.py was not enough. You also have to append the path of the parent directory if you get module not found error.

root :
 |
 |__SiblingA:
 |    \__A.py
 |     
 |__SiblingB:
 |      \_ __init__.py
 |      \__B.py
 |

To import B.py from A.py, you have to do the following

import sys
  
# append the path of the parent directory
sys.path.append("..")

from SiblingB import B
print("B is successfully imported!")
Shekhar
  • 167
  • 1
  • 11
0

The reason for

ValueError: Attempted relative import beyond toplevel package

is that A is the same directory level as Driver.py. Hence, ..A in from ..A import Account is beyond top-level package.

You can solve this by create a new folder named AandB together with __init__py in this new folder, and then move A and B folders into AandB folder. The directory structure is as following:

The directory structure

Correspondingly, the content in Driver.py should be modified as from AandB.B import Test.