I am having the following directory structure and I'm new to python. In folder bin I have a single file "script.py" in which I want to import "module.py" from code package. I have seen many solutions on stackoverflow to this problem that involve modifying sys-path or giving full pathname. Is there any way I could import these with an import statement that works relatively, instead of specifying full path?
project/
bin/
script.py
code/
module.py
__init__.py
2 Answers 2
To make sure that bin/script.py can be run without configuring environment, add this preambule to script.py before from code import module line (
from twisted/bin/_preambule.py):
# insert `code/__init__.py` parent directory into `sys.path`
import sys, os
path = os.path.abspath(sys.argv[0]) # path to bin/script.py
while os.path.dirname(path) != path: # until top-most directory
if os.path.exists(os.path.join(path, 'code', '__init__.py')):
sys.path.insert(0, path)
break
path = os.path.dirname(path)
The while loop is to support running it from bin/some-other-directory/.../script.py
2 Comments
setup.py for project and install it before running any scripts. The installation process puts code into a directory that is already in sys.path i.e., sys.path is not modified in this case. Also you can import any code from any source using imp (or importlib in Python 3), but you should not use it in ordinary circumstances.While correct, I think that the "dynamically add my current directory to the path" is a dirty, dirty hack.
Add a (possibly blank) __init__.py to project. Then add a .pth file containing the path to project to your sites-packages directory. Then:
from project.code import module
This has two advantages, in my opinion:
1) If you refactor, you just need to change the from project.code line and avoid messing with anything else.
2) There will be nothing special about your code -- it will behave exactly like any other package that you've installed through PyPi.
It may seem messy to add your project directory to your PYTHONPATH but I think it's a much, much cleaner solution than any of the alternatives. Personally, I've added the parent directory that all of my python code lives in to my PYTHONPATH with a .pth file, so I can deal with all of the code I write just like 3rd party libraries.
I don't think that there is any issue with cluttering up your PYTHONPATH, since only folders with an __init__.py will be importable.
3 Comments
code Python package assuming common ancestry that is implied by the question ("relative import") 2. And it would be pointless to add the current directory because it is already in sys.path when script.py is run as a script.sys.path is a dirty hack for sure. 1. .pth files might be even worse unless it is created by setup.py upon installation of the package. If you are creating files; why wouldn't you create a simple setup.py file and install the module properly? And why do you need project directory to be a Python package? It is enough if code package is accessible (I assume it is not a real name otherwise it is shadowing the stdlib module with the same name) in this case code package behaves as any other package. 2. PYTHONPATH is even more global than a .pth file (more potential damage)Explore related questions
See similar questions with these tags.