- Get the path of the currently executing python script using import. (Python recipe) by Jitender Cheema
- !/usr/bin/python
- BASE_PATH is the absolute path of ../.. relative to this script location
- add ../../scripts (relative to the file (!) and not to the CWD)
- Python 101: How to Find the Path of a Running Script
- Further Reading
- Get the path of the currently executing python script using import. (Python recipe) by Jitender Cheema
- !/usr/bin/python
- BASE_PATH is the absolute path of ../.. relative to this script location
- add ../../scripts (relative to the file (!) and not to the CWD)
Get the path of the currently executing python script using import. (Python recipe) by Jitender Cheema
William B. good one, understood.How to do in Windows ??
Why not use sys.path[0] ? Statement ‘print sys.path[0]’ does what you want, see http://docs.python.org/lib/module-sys.html
addition: full path to running script. Well, to get the path + script file do something like: ‘print os.path.join(sys.path[0], sys.argv[0])’
As I said there can be many ways, one of the way is using: sys.path[0] sys.path is List of paths.. Try this in python interpreter import sys print sys.path # prints out a whole list of python module paths.. print sys.path[0] # prints out » Now try same as a python script and compare: import sys print sys.path # prints out a whole list of python module paths.. print sys.path[0] # prints out cwd
The current directory can be interpreted more than one way. In order to understand what is going on with the following short section of code, put it in a file named pwd.py, then do the following:
mkdir junk cd junk python ../pwd.py
You need to make sure that your current working directory (the cd command destination) is not the same as the directory containing the Python script. After that it is self explanatory except for the .EXE path. Try running the script through PY2EXE first, and this will make more sense.
import os,sys print "CWD: ",os.getcwd() print "Script: ",sys.argv[0] print ".EXE: ",os.path.dirname(sys.executable) print "Script dir: ", os.path.realpath(os.path.dirname(sys.argv[0])) pathname, scriptname = os.path.split(sys.argv[0]) print "Relative script dir: ",pathname print "Script dir: ", os.path.abspath(pathname)
sys.path[0] is not the same. Here’s my (slightly) cleaned up version:
import sys import os, os.path def get_my_path(): import fake path = str(fake).split()[3][1:-9] os.remove( os.path.join( path, 'fake.pyc' ) ) return path def do(): print "sys.path[0]: %s" % sys.path[0] print "os.getcwd(): %s" % os.getcwd() print "get_my_path(): %s" % get_my_path()
Import this module from a different directory (make sure it’s in your PYTHONPATH) and invoke do(). You’ll see that the first two paths are the directory you’re invoking from, but the third is the directory containing the module.
Thanks to all for your inputs.
Just summarizing what worked best for me (I needed to get the path of the current module). It was tested on both Linux and Windows, with all the usages I could think of.
os.path.dirname( os.path.realpath( __file__ ) )
The reason for the additionnal call to os.path.realpath() is that omitting it will only work if you run the script by specifying its full path (or, under Windows, if you only type the python script name — this is because Windows has Python.exe associated to that extension and will specify the full path of the script whenever it invokes it).
So, to import from a location relative to the current path, you can do:
import os # BASE_PATH is the absolute path of ../.. relative to this script location BASE_PATH = reduce (lambda l,r: l + os.path.sep + r, os.path.dirname( os.path.realpath( __file__ ) ).split( os.path.sep )[:-2] ) # add ../../scripts (relative to the file (!) and not to the CWD) sys.path.append( os.path.join( BASE_PATH, "scripts" ) ) import foobar if __name__ == '__main__': .
i get the same path info for either BASE_PATH. very clever idea — would like to make it work. if you can, please see if i missed soemthing? i created a folder one level up names scripts, and put a module in there names foo.py foo.py is just a hello world. the error is no module foo found. tia, greg
!/usr/bin/python
import os from os import path import sys
BASE_PATH is the absolute path of ../.. relative to this script location
BASE_PATH = reduce (lambda l,r: l + os.path.sep + r, os.path.dirname( os.path.realpath( __file__ ) ).split( os.path.sep )[:-2] )
print BASE_PATH, ‘original base path’
add ../../scripts (relative to the file (!) and not to the CWD)
sys.path.append( os.path.join( BASE_PATH, «../scripts/» ) )
print BASE_PATH, ‘modified base path’
Python 101: How to Find the Path of a Running Script
This topic is actually more complicated then it first appears. In this article, we’ll spend a little time looking at this problem and some of the solutions.
Several years ago, one of my friends on the wxPython users mailing list told me that he uses the following:
import os script_path = os.path.dirname(os.path.abspath( __file__ ))
This works for me and is what I currently use. The code above returns the absolute path, by the way. According to the documentation, it is the equivalent of
import os os.path.normpath(join(os.getcwd(), path))
I’ve also seen people recommending the following similar solution:
import os os.path.dirname(os.path.realpath(__file__))
The documentation states that realpath will return the canonical path of the specified filename, eliminating any symbolic links encountered in the path, which sounds like it may be better than the solution I’ve been using.
Regardless, as some are likely to point out, you cannot use __file__ from within IDLE / the interpreter. If you do, you’ll get the following error:
Traceback (most recent call last): File "", line 1, in __file__ NameError: name '__file__' is not defined
You’ll end up with the same error if you happen to “freeze” your application by creating an executable with something like py2exe. For cases like this, some would recommend the following as an alternative:
import os os.path.dirname(sys.argv[0])
Now this will not work if you happen to call your script from another script. I’m also pretty sure that when I tried this with a frozen application and called the executable from a shortcut, it was returning the shortcut’s path instead of the executable’s. However, I may be getting that confused with os.getcwd() which will definitely not work reliably.
The solution I ended up with for the executables I created with py2exe was this one:
import os, sys os.path.abspath(os.path.dirname(sys.argv[0]))
I’m pretty sure one of the core developers from wxPython had recommended using that, but I can’t be sure as I don’t seem to have that email any longer. Regardless, Mark Pilgrim, author of Dive Into Python, also recommends using os.path.abspath.
For now I think I will stick with either os.path.abspath or os.path.realpath for scripts and the above variation for my frozen Windows applications. I would be interested in hearing about your solution though. Let me know if you’ve found anything that works cross-platform and/or for frozen scripts.
Further Reading
Get the path of the currently executing python script using import. (Python recipe) by Jitender Cheema
William B. good one, understood.How to do in Windows ??
Why not use sys.path[0] ? Statement ‘print sys.path[0]’ does what you want, see http://docs.python.org/lib/module-sys.html
addition: full path to running script. Well, to get the path + script file do something like: ‘print os.path.join(sys.path[0], sys.argv[0])’
As I said there can be many ways, one of the way is using: sys.path[0] sys.path is List of paths.. Try this in python interpreter import sys print sys.path # prints out a whole list of python module paths.. print sys.path[0] # prints out » Now try same as a python script and compare: import sys print sys.path # prints out a whole list of python module paths.. print sys.path[0] # prints out cwd
The current directory can be interpreted more than one way. In order to understand what is going on with the following short section of code, put it in a file named pwd.py, then do the following:
mkdir junk cd junk python ../pwd.py
You need to make sure that your current working directory (the cd command destination) is not the same as the directory containing the Python script. After that it is self explanatory except for the .EXE path. Try running the script through PY2EXE first, and this will make more sense.
import os,sys print "CWD: ",os.getcwd() print "Script: ",sys.argv[0] print ".EXE: ",os.path.dirname(sys.executable) print "Script dir: ", os.path.realpath(os.path.dirname(sys.argv[0])) pathname, scriptname = os.path.split(sys.argv[0]) print "Relative script dir: ",pathname print "Script dir: ", os.path.abspath(pathname)
sys.path[0] is not the same. Here’s my (slightly) cleaned up version:
import sys import os, os.path def get_my_path(): import fake path = str(fake).split()[3][1:-9] os.remove( os.path.join( path, 'fake.pyc' ) ) return path def do(): print "sys.path[0]: %s" % sys.path[0] print "os.getcwd(): %s" % os.getcwd() print "get_my_path(): %s" % get_my_path()
Import this module from a different directory (make sure it’s in your PYTHONPATH) and invoke do(). You’ll see that the first two paths are the directory you’re invoking from, but the third is the directory containing the module.
Thanks to all for your inputs.
Just summarizing what worked best for me (I needed to get the path of the current module). It was tested on both Linux and Windows, with all the usages I could think of.
os.path.dirname( os.path.realpath( __file__ ) )
The reason for the additionnal call to os.path.realpath() is that omitting it will only work if you run the script by specifying its full path (or, under Windows, if you only type the python script name — this is because Windows has Python.exe associated to that extension and will specify the full path of the script whenever it invokes it).
So, to import from a location relative to the current path, you can do:
import os # BASE_PATH is the absolute path of ../.. relative to this script location BASE_PATH = reduce (lambda l,r: l + os.path.sep + r, os.path.dirname( os.path.realpath( __file__ ) ).split( os.path.sep )[:-2] ) # add ../../scripts (relative to the file (!) and not to the CWD) sys.path.append( os.path.join( BASE_PATH, "scripts" ) ) import foobar if __name__ == '__main__': .
i get the same path info for either BASE_PATH. very clever idea — would like to make it work. if you can, please see if i missed soemthing? i created a folder one level up names scripts, and put a module in there names foo.py foo.py is just a hello world. the error is no module foo found. tia, greg
!/usr/bin/python
import os from os import path import sys
BASE_PATH is the absolute path of ../.. relative to this script location
BASE_PATH = reduce (lambda l,r: l + os.path.sep + r, os.path.dirname( os.path.realpath( __file__ ) ).split( os.path.sep )[:-2] )
print BASE_PATH, ‘original base path’
add ../../scripts (relative to the file (!) and not to the CWD)
sys.path.append( os.path.join( BASE_PATH, «../scripts/» ) )
print BASE_PATH, ‘modified base path’