views:

58

answers:

2

So after a few hours, I discovered the cause of a bug in my application. My app's source is structured like:

main/
    __init__.py
    folderA/
        __init__.py
        fileA.py
        fileB.py

Really, there are about 50 more files. But that's not the point. In main/__init__.py, I have this code: from folderA.fileA import *

in folderA/__init__.py I have this code:

sys.path.append(pathToFolderA)

in folderA/fileB.py I have this code:

from fileA import *

The problem is that fileA gets imported twice. However, I only want to import it once.

The obvious way to fix this (to me atleast) is to change certain paths from path to folderA.path

But I feel like Python should not even have this error in the first place. What other workarounds are there that don't require each file to know it's absolute location?

+3  A: 

Don't modify sys.path this way, as it provides two ways (names) to access your modules, leading to your problem.

Use absolute or unambiguous-relative imports instead. (The ambiguous-relative imports can be used as a last resort with older Python versions.)

folderA/fileB.py

from main.folderA.fileA import *   # absolute
from .fileA import *               # unambiguous-relative
from fileA import *                # ambiguous-relative

Of course, you should be using specific names in place of that star.

Roger Pate
+4  A: 
  • Modifying sys.path isn't something you do in a real program. It hurts modularity and portability with no gain over setting PYTHONPATH permanently or putting your module in a place Python can find it.

  • Never ever ever ever use import *. It pollutes your namespace and makes your code unpredictable.

  • You don't want folderA on sys.path. It is a subpackage of main and should always be treated as such. Always use absolute imports going to top-level packages: import main.folderA rather than import folderA or anything else; it will make your code a lot easier to follow and move around and install.

Mike Graham