1

The file structure of the code I am working with right now is as follows:

school_project/
     __init__.py       #(empty)
     main_functions/
         __init__.py   #(empty)
         render.py
         filter.py
     helper_functions/
         __init__.py   #(empty)
         string.py
         utility.py

Currently, I need to use functions founded in utility.py in the file render.py. My first attempt at solving this problem was to do import ..helper_functions.utility in the file render.py.

Unfortunately, it was met with the following error message.

import ..helper_functions.utility
       ^
SyntaxError: invalid syntax

First off, I have no idea why this relative import is not working.

Secondly, should I just use an absolute import instead? In the form import school_project.helper_functions.utility? If so, would I then need to add the directory that school_project/ is currently in to PYTHONPATH? How would I do this?

Would I just modify my computer's PATH and PYTHONPATH will adapt accordingly? Or are they separate entities and the process is a bit more involved? Ive looked at other threads but they all seem to modify PYTHONPATH at run time in the python script itself, something I see as a giant potential origin of bugs in the future.

AlanSTACK
  • 5,525
  • 3
  • 40
  • 99

2 Answers2

1

This is the way you should do it:

  from ..helper_functions import utility

This will not work if you run your python program normally due to relative imports.

This is the way you are supposed to run it:

python3 -m helper_functions.utility

But it's somewhat verbose, and doesn't mix well with a shebang line like #!/usr/bin/env python3.

Although it's not unique. Your package structure is more complex. You'll need to include the directory containing your package directory in PYTHONPATH, and do it like this.

from mypackage.mymodule import as_int

You can also do this. But this is not recommanded for beginners. You just frob the PYTHONPATH in code first with this...

import sys
import os

PACKAGE_PARENT = '..'
SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))))
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))

from mypackage.mymodule import as_int
Tristan
  • 2,000
  • 17
  • 32
0

Absolute imports are recommended in Pep 8:

Absolute imports are recommended, as they are usually more readable and tend to be better behaved (or at least give better error messages) if the import system is incorrectly configured (such as when a directory inside a package ends up on sys.path ):

As for the PYTHONPATH, setting it once per terminal session where you work on the project might be best for now. Once you continue on to use an IDE like pycharm, this will be managed for you automagically

renefritze
  • 2,167
  • 14
  • 25
  • 1
    Relative imports are not so discouraged anymore, see this answer: https://stackoverflow.com/questions/4209641#answer-16748366 – pawamoy Jun 11 '16 at 10:08
  • 1
    This phrasing is not included in the [current revision of pep8](https://www.python.org/dev/peps/pep-0008/). Instead it says this: _Absolute imports are recommended, as they are usually more readable and tend to be better behaved (or at least give better error messages) if the import system is incorrectly configured (such as when a directory inside a package ends up on sys.path ):_ – Håken Lid Jun 11 '16 at 10:17