Experimenting with ways to import in python
Reference: Understanding Python imports, init.py and pythonpath — once and for all
Assume this directory structure:
- python-imports (root)
- scripts
- ex1.py
- ex2.py
- README.md
ex2.py
imports from ex1.py
using import ex1
Running ex1.py
and ex2.py
from command line: Works!
$ cd scripts
$ python -m ex1 # works
$ python -m ex2 # works
From the link above:
The output from sys.path will always contain the current directory at index 0! The current directory being the one where the script being run resides. This is the reason importing is fairly straightforward when both the caller and callee modules reside within the same directory.
Running ex1.py
and ex2.py
using PyCharm GUI: Works!
- From editor window, right-click and select "Run", or hit
Ctrl + Shift + F10
- Also works if using debugger.
- This works because the IDE knows to add the location of the file to
sys.path
. Note that the following is the first line of output when run:
C:\Users\vr229e\AppData\Local\r-miniconda\python.exe C:/Nayef/python-imports/scripts/ex2.py
Running ex1.py
and ex2.py
using PyCharm console: Doesn't work!
- In
ex2.py
, place cursor on the lineimport ex1
, and hitCtrl + Enter
to run. This will fail. - This doesn't work because the Console doesn't know about the
scripts
subfolder. Note that it outputs a line like this:
import sys; print('Python %s on %s' % (sys.version, sys.platform))
sys.path.extend(['C:\\Nayef\\python-imports', 'C:/Nayef/python-imports'])
- If you print
sys.path
in the console, you'll see that it doesn't includeC:/Nayef/python-imports/scripts/
- To fix this, you can just run this in console:
sys.path.append('scripts')
orsys.path.extend(['scripts'])
. Another option is to change the import statement toimport scripts.ex1 as ex1
, but this is less preferred.
Running from command line (or using GUI to mimic this) will know which directory the current script resides in, and will have no problem importing other scripts in the same directory.
However, when running line-by-line in the PyCharm console, we may need to
use sys.path.append()
to add the sub-directory name. By default, the console
only knows about the root directory.
-
os.path.dirname(__file__)
works when run from CLI, but not when run line-by-line in PyCharm console. -
Path(__file__).parents[0]
will get the directory of the current file.Path(__file__).parents[1]
will get the parent of that directory, and so on.
Assume this structure:
- python-imports (root)
- src
- ex2.py
- utils.py # contains function read_yaml()
- config.yaml
- README.md
Q: How to call read_yaml
in ex2.py
to read in config.yaml
, without
hardcoding paths.
Ans. Use this setup:
# ex2.py
import utils
from pathlib import Path
f = Path(__file__).parents[1].joinpath('config.yaml')
config_yaml = utils.read_yaml(f)