You have been an answer to my prayers. I'm a beginner and I've been struggling with importing and understanding the path/environment_variables/etc. And I come across this little gem in the middle of the night while pulling my hair out telling myself I guess i'm just stupid.. now i'm merely stupid and informed.. Thank you so much.
Why would you think you’re stupid? If the docs you’re reading aren’t giving you what you need to know, you’re either using the wrong docs (in which case just try another one) or the docs have failed at their purpose and it’s a bug.
This article de-emphasises an important piece of the puzzle: the -m switch to the python command. This runs a Python file as a module rather than a script, complete with module-ish rules for imports, but with __name__=="__main__" so the script-ish code in it runs. The author says "I am unaware of a clean solution to this problem [of a Python file that could be run as a script or used as a module]", and then mentions -m as a sub-bullet point without explanation. But this IS the clean solution!
Here is a quick example of how it works. Consider the following directory layout:
You would expect foo.py to start with these lines:
import pkg.sub.bar
import pkg.baz
As the article explains, these will not work if you just run foo.py as a script, because sys.path will start with "topdir/pkg/sub/":
python pkg/sub/foo.py
The simple fix here is to run the python file as a module, with "topdir/" as your working directory, so sys.path starts with "topdir/":
python -m pkg.sub.foo
After briefly mentioning python -m, the article has quite a lot of text on how to modify sys.path instead. That variable is interesting for understanding what's going on, but you should certainly not be modifying it. The exception is that if you have multiple different root directories containing packages (multiple directories like "topdir"), in which case you should indirectly modify sys.path by setting the environment variable PYTHONPATH. Code should never touch sys.path because the location of packages on your computer is a property of that computer's environment, not of the code.
I guess "one way to do the thing" motto is at work here - run python as modules every time. I guess the script part should run the file it contains as a module for graceful fallback
4 comments
[ 3.0 ms ] story [ 16.6 ms ] threadHere is a quick example of how it works. Consider the following directory layout:
You would expect foo.py to start with these lines: As the article explains, these will not work if you just run foo.py as a script, because sys.path will start with "topdir/pkg/sub/": The simple fix here is to run the python file as a module, with "topdir/" as your working directory, so sys.path starts with "topdir/": After briefly mentioning python -m, the article has quite a lot of text on how to modify sys.path instead. That variable is interesting for understanding what's going on, but you should certainly not be modifying it. The exception is that if you have multiple different root directories containing packages (multiple directories like "topdir"), in which case you should indirectly modify sys.path by setting the environment variable PYTHONPATH. Code should never touch sys.path because the location of packages on your computer is a property of that computer's environment, not of the code.