0

I've created two modules in the same directory:

.
├── mod1.py
├── mod2.py

There is no __init__.py, I don't want to create this as a package, I'm just creating a simple script which I have modularized by breaking into different modules.

My intention is to run mod1.py using python mod1.py

~/junk/imports$ cat mod1.py 
from . import mod2

print(mod2.some_expr)


$ cat mod2.py
some_expr = 'hello world!'

Although I know that directly using import mod1 will work, but I'm deliberately not using it so that my module name doesn't clash with built in modules (which I felt is a good practice)

I'm getting the following errors with python2 and python3

~/junk/imports$ python3 --version
Python 3.4.3
kartik@kartik-lappy:~/junk/imports$ python3 mod1.py 
Traceback (most recent call last):
  File "mod1.py", line 1, in <module>
    from . import mod2
SystemError: Parent module '' not loaded, cannot perform relative import


~/junk/imports$ python2 --version
Python 2.7.11
~/junk/imports$ python2 mod1.py 
Traceback (most recent call last):
  File "mod1.py", line 1, in <module>
    from . import mod2
ValueError: Attempted relative import in non-package

Most of the questions like this on StackOverflow deal with packages, but I'm not using packages. I just want to run it as a simple script.

My question is not about how to do it, but I want to know the reason behind the above not working.

Kartik Anand
  • 4,513
  • 5
  • 41
  • 72
  • Why are you not using an __init__.py file? Wouldn't this mean that when python checks the . directory, it realises theres no init file and will throw an exception? i.e attempted relative import in non-package – Alan Kavanagh May 28 '16 at 17:21
  • I'm not using `__init__.py` because I don't want to create a package. I'm just creating simple scripts. I want to understand the reason behind not allowing "explicit" relative imports. – Kartik Anand May 28 '16 at 17:28

1 Answers1

1

You shouldn't use relative, but absolute import:

import mod2
print(mod2.some_expr)

The documentation is pretty good, and this SO answers gives an alternative using importlib.

If a handmade module clash with a builtin module, the proper way to go is probably to rename it, eventually through addition of a {pre,suf}fix. Another is to use importlib.

The motivation underlying these limitation can be found in the PEP 328, and comes mainly from BDFL preferences, over all other solutions.

Community
  • 1
  • 1
aluriak
  • 5,559
  • 2
  • 26
  • 39
  • I know I should, but here I'm using explicit relative import. Is there a reason why it is not recommended? – Kartik Anand May 28 '16 at 17:20
  • [PEP 328](https://www.python.org/dev/peps/pep-0328) gives informations about imports. As far as i know, relative imports are generally not recommended, and only available inside packages. From the PEP: *all import statements be absolute by default (searching sys.path only) with special syntax (leading dots) for accessing package-relative imports.* – aluriak May 28 '16 at 17:23
  • I meant to import `mod2` only. I've corrected the question! – Kartik Anand May 28 '16 at 17:27
  • I can see the rationale for using absolute imports with package. But what about non-packages, for simple scripts, I thought relative imports should work. – Kartik Anand May 28 '16 at 17:32
  • [Python glossaries](https://docs.python.org/3/glossary.html#term-package) explains that that all packages are modules, but not all modules are packages. The `__path__` attribute, specific to packages, allows them to have a relative import. While modules that are not packages have no `__path__` attribute, it's impossible to get a relative import. – aluriak May 28 '16 at 17:38