If I moved CreateUser.py to the main user_management directory, I can easily use: import Modules.LDAPManager to import LDAPManager.py --- this works.
Please don't . Thus, the LDAPManager used by CreateUser will not be the same as the one imported through another import. This can create problems when you have some kind of global condition in the module or during pickling / spilling. Avoid imports that only work because the module is in the same directory.
If you have a package structure, you should:
Use relative imports, i.e. if CreateUser.py is in Scripts/ :
from ..Modules import LDAPManager
Note that this one (note the past tense) was discouraged by PEP 8 just because older versions of python did not support them very well, but this problem was solved many years ago. The current version of PEP 8 offers them as an acceptable alternative to absolute imports. I really love them inside the packages.
Use absolute imports using the fully qualified package name ( CreateUser.py in Scripts/ ):
from user_management.Modules import LDAPManager
In order for the second to work, the user_management package must be installed inside PYTHONPATH . During development, you can configure the IDE to make this happen without having to manually add calls to sys.path.append anywhere.
It also seemed strange to me that Scripts/ is a subfolder. Since in a real installation, the user_management module will be installed under the site-packages found in the lib/ directory (which directory is used to install the libraries in your OS), while the scripts must be installed in the bin/ directory (depending on what it contains executable files for your OS).
In fact, I believe that Script/ should not even be under user_management . It must be at the user_management level. Thus, you do not need to use -m , but you just need to make sure that the package can be found (this is again a matter of configuring the IDE, installing the package correctly, or using PYTHONPATH=. python Scripts/CreateUser.py to run scripts from the correct path).
Thus, I would use the following hierarchy:
user_management (package) | |------- __init__.py | |------- Modules/ | | | |----- __init__.py | |----- LDAPManager.py | |----- PasswordManager.py | Scripts/ (*not* a package) | |----- CreateUser.py |----- FindUser.py
Then the code CreateUser.py and FindUser.py should use absolute import to import the modules:
from user_management.Modules import LDAPManager
During installation, you will make sure that user_management ends somewhere in PYTHONPATH and scripts inside the directory for executable files so that they can find modules. During development, you either rely on the IDE configuration or run CreateUser.py add the parent Scripts/ directory to PYTHONPATH (I mean the directory that contains both user_management and Scripts ):
PYTHONPATH=/the/parent/directory python Scripts/CreateUser.py
Or you can change PYTHONPATH globally, so you do not need to specify this every time. On UNIX OS (Linux, Mac OS X, etc.) you can change one of the shell scripts to define the external variable PYTHONPATH , on Windows you need to change the settings of environment variables.
Addendum I believe that if you are using python2, it is better to avoid implicit relative imports by setting:
from __future__ import absolute_import
at the top of your modules. Thus, import X always means importing a top-level module X and will never try to import the X.py file in the same directory (unless that directory is in PYTHONPATH ). Thus, the only way to do relative imports is to use explicit syntax ( from . import X Import from . import X ), which is better (explicit is better than implicit).
This ensures that you will never be able to use "dummy" implicit relative imports, as they will increase the clarity of ImportError , signaling that something is wrong. Otherwise, you can use a module that is not what you think.