Reputation: 6842
In a certain programme I have an abstract class that should be implemented in two different sub-packages for different purposes. A simplified version of this structure is:
programme/
__init__.py
Abstract.py
pkgA/
__init__.py
ClassA.py
pkgB/
__init__.py
ClassB.py
Up to Python 3.2 (I believe), it was possible to import the Abstract class within the a subfolder with a relative reference:
from .. import Abstract
Which with Python 3.6 devolves the error message:
ValueError: attempted relative import beyond top-level package
The classical (and ugly) alternative is to add the parent folder to the path at run time:
import sys
import os
sys.path.append(os.getcwd() + '/..')
from programme import Abstract
But this also fails:
ModuleNotFoundError: No module named 'programme'
How is this now done with Python 3.6? Preferably without modifying the path at run time.
Upvotes: 0
Views: 574
Reputation: 31
You can use a __init__.py at the top level, programme/__init__.py, then import in the sub-module from programme.
Example:
# programme/__init__.py
from .Abstrac import Abstract
# programme/Abstract.py
class Abstract:
def __init__(self):
print('Abstract')
# programme/pkgA/ClassA.py
from programme import Abstract
class ClassA(Abstract):
def __init__(self):
super().__init__()
if __name__ == '__main__':
a = ClassA()
Note, if you running as a script you should do:
$ cd programme
$ python -m programme.classA.ClassA
Abstract
Upvotes: 2
Reputation: 446
You need to a level higher than programme.
This needs to be added to the code:
import os, sys
current_dir = os.path.dirname(os.path.join(os.getcwd(), __file__))
sys.path.append(os.path.normpath(os.path.join(current_dir, '..', '..')))
from programme import Abstract
This has worked when doing python3.7 ClassA.py
on programme/pkgA
and it was picked from this response: Ultimate answer to relative python imports
Upvotes: 1