5

I have a Python package called Util. It includes a bunch of files. Here is the include statements on top of one of the files in there:

from config_util import ConfigUtil #ConfigUtil is a class inside the config_util module
import error_helper as eh

This works fine when I run my unit tests.

When I install Util in a virtual environment in another package everything breaks. I will need to change the import statements to

from Util.config_util import ConfigUtil
from Util import error_helper as eh

and then everything works as before. So is there any point in using the first form or is it safe to say that it is better practice to always use the second form?

If there is no point in using the first form, then why is it allowed?

Barka
  • 8,764
  • 15
  • 64
  • 91
  • 2
    you've tagged `python-3.x` but are using implicit relative imports which were removed in python3. My guess is you're running [`python Util/foo.py` instead of `python -m Util.foo`](https://github.com/asottile/scratch/wiki/PythonPathSadness) for your tests – anthony sottile Nov 28 '18 at 02:21

2 Answers2

1

Just wrong:

from config_util import ConfigUtil
import error_helper as eh

It will only work if you happen to be in the directory Util, so that the imports resolve in the current working directory. Or you have messed with sys.path using some bad hack.

Right (using absolute imports):

from Util.config_util import ConfigUtil
import Util.error_helper as eh

Also right (using relative imports):

from .config_util import ConfigUtil
import .error_helper as eh

There is no particular advantage to using relative imports, only a couple of minor things I can think of:

  • Saves a few bytes in the source file (so what / who cares?)
  • Enables you to rename the top level without editing import statements in source code (...but how often do you do that?)
wim
  • 338,267
  • 99
  • 616
  • 750
  • renaming... as part of going to python 3 i just this did that and moved to all-absolute. lots of sed used. specifically wrt relative, those were some of the hardest to handle as their import path patterns are harder to target than the absolute imports. fwiw, i ended up converting lots of ‘import top.x.y.z’ as ‘from top.x.y import z’. the code is shorter and has some isolation from future renames that way. – JL Peyret Nov 28 '18 at 16:18
0

For your practical problems, maybe this answer can help you.

Regarding your direct question: there's not a lot to it, but they let you move files and rename containing directories more easily. You may also prefer relative imports for stylistic reasons; I sure do.

The semantics are the same if the paths are correct. If your module is foo.bar, then from foo.bar.baz import Baz and from .baz import Baz are the same. If they don't do the same, then you're likely calling your Python file as a script (python foo/bar.py), in which case it will be module __main__ instead of foo.bar.

Silly Freak
  • 4,061
  • 1
  • 36
  • 58