ValueError: attempted relative import beyond top-level package - part 2

Resolving relative modules

In PEP 328 -- Imports: Multi-Line and Absolute/Relative we can find the way the python interpreter should resolve the relative import:

Relative imports use a module's __name__ attribute to determine that module's position in the package hierarchy.

In other words, the algorithm to resolve the module is based on the values of __name__ and __package__ variables. However, When invoking a python script, __name__ is __main__ and __package__ is None.

Let's see how the algorithm should handle this special case:

If the module's name does not contain any package information (e.g., it is set to __main__), then relative imports are resolved as if the module were a top-level module, regardless of where the module is actually located on the file system.

Let's add some log messages to the sample project, which demonstrate this special case.

root/data.py with logs
 print('__file__={0:<35} | __name__={1:<25} | __package__={2:<25}'.format(__file__,__name__,str(__package__)))

 size = 10
root/package/program.py with logs
 print('__file__={0:<35} | __name__={1:<25} | __package__={2:<25}'.format(__file__,__name__,str(__package__)))

 from .. import data
 print("data.size => {0}".format(data.size))
Invoking program.py
 Y:/root>python package/program.py
 __file__=package/program.py                  | __name__=__main__                  | __package__=None
 Traceback (most recent call last):
   File "package/program.py", line 3, in <module>
     from .. import data
 ValueError: attempted relative import beyond top-level package

As we can see in the above output when invoking script __name__ is __main__ and __package__ is None. Since the python interpreter does not have any information about the package the module belong, it complains that it can not find the parent package.

In the next part, we see how to resolve this problem.