1

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
asked Dec 29, 2013 at 3:51

2 Answers 2

4

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

answered Dec 29, 2013 at 4:54
Sign up to request clarification or add additional context in comments.

2 Comments

is there any other way possible than modifying sys.path?
@bullseye: yes, there are other ways e.g., create 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.
1

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.

answered Dec 29, 2013 at 10:37

3 Comments

will the import be absolute then, i mean project.code.module? It won't be relative right, but still a cleaner solution, i added a PYTHONPATH variable in my environment variables.
1. My code doesn't add the current directory to the path. It searches for the parent directory that contains 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.
Modifying 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)

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.