views:

906

answers:

2

I'm building a simple helper script for work that will copy a couple of template files in our code base to the current directory. I don't, however, have the absolute path to the directory where the templates are stored. I do have a relative path from the script but when I call the script it treats that as a path relative to the current working directory. Is there a way to specify that this relative url is from the location of the script instead?

A: 

See sys.path As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter.

Use this path as the root folder from which you apply your relative path

>>> import sys
>>> import os.path
>>> sys.path[0]
'C:\\Python25\\Lib\\idlelib'
>>> os.path.relpath(sys.path[0], "path_to_libs") # if you have python 2.6
>>> os.path.join(sys.path[0], "path_to_libs")
'C:\\Python25\\Lib\\idlelib\\path_to_libs'
Tom Leys
That's not necessarily true. Usually sys.path[0] is an empty string or a dot, which is a relative path to the current directory. If you want the current directory, use os.getcwd.
Jason Baker
The original poster commented that the current working directory is the wrong place to base the relative path from. You are correct in saying that sys.path[0] is not always valid.
Tom Leys
+7  A: 

In the file that has the script, you want to do something like this:

import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, '/relative/path/to/file/you/want')

This will give you the absolute path to the file you're looking for. Note that if you're using setuptools, you should probably use its package resources API instead.

UPDATE: I'm responding to a comment here so I can paste a code sample. :-)

Am I correct in thinking that __file__ is not always available (e.g. when you run the file directly rather than importing it)?

I'm assuming you mean the __main__ script when you mention running the file directly. If so, that doesn't appear to be the case on my system (python 2.5.1 on OS X 10.5.7):

#foo.py
import os
print os.getcwd()
print __file__

#in the interactive interpreter
>>> import foo
/Users/jason
foo.py

#and finally, at the shell:
~ % python foo.py
/Users/jason
foo.py

However, I do know that there are some quirks with __file__ on C extensions. For example, I can do this on my Mac:

>>> import collections #note that collections is a C extension in Python 2.5
>>> collections.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-
dynload/collections.so'

However, this raises an exception on my Windows machine.

Jason Baker
Awesome! __file__ was just what I was looking for.
docgnome
Am I correct in thinking that __file__ is not always available (e.g. when you run the file directly rather than importing it)?
Stephen Edmonds
@Stephen Edmonds I'm using it a file that I run, rather than import, and it works great.
docgnome