I find it interesting that I get something different:
In [1]: import path
path.pyc
In [2]: path.__file__
Out[2]: 'path.pyc'
In [3]: path.__file__.rstrip("c")
Out[3]: 'path.py'
In [4]: from os.path import abspath, realpath
In [5]: realpath(path.__file__.rstrip("c"))
Out[5]: '/home/andrew/sym/sym/path.py'
In [6]: realpath(abspath(path.__file__.rstrip("c")))
Out[6]: '/home/andrew/sym/sym/path.py'
I get the same thing for realpath() and realpath(abspath())
It seems to me you can just use:
In [1]: import path
path.pyc
In [2]: from os.path import abspath
In [3]: realpath(path.__file__.rstrip("c"))
Out[3]: '/home/andrew/sym/sym/path.py'
By the way, I am in /home/andrew/sym and path is symlinked from
/home/andrew/sym/sym/path.py to /home/andrew/sym/path.py
As you can see above, I get the wrong think if I do that. It's very
strange that we're getting different things. I'm using python 2.4,
maybe it was updated in 2.5?
After doing a little testing, it seems that realpath was in fact
improved between 2.4 and 2.5. I need to stick with 2.4, so the
abspath() call is still necessary for me.
Regardless, the answer to my question is that there's no good built-in
way to do this. Even the code above fails for some cases (say the
symlink is named just "c"), making the problem non-trivial. To me,
this is a failure of python's "batteries included". Is this worthy of
a PEP? I'd like to add something like "__absfile__" or maybe
"os.path.absolute_script_path()".
Sample implementation:
def scriptpath():
from inspect import currentframe
file = currentframe().f_back.f_locals.get('__file__', None)
if file.endswith(".pyc"): file = file.rstrip("c")
from os.path import realpath, abspath
return realpath(abspath(file))
Testing:
~/python>ls -l foo.py* c sym/*
lrwxrwxrwx 1 bgolemon asic 10 Jul 28 10:46 c -> sym/
bar.py*
lrwxrwxrwx 1 bgolemon asic 10 Jul 28 10:38 foo.py -> sym/
bar.py*
-rw-rw-r-- 1 bgolemon asic 149 Jul 28 10:57 foo.pyc
-rwxrwx--- 1 bgolemon asic 76 Jul 28 10:53 sym/bar.py*
-rw-rw-r-- 1 bgolemon asic 149 Jul 28 10:58 sym/bar.pyc
~/python>cat sym/bar.py
#!/usr/bin/env python
from scriptpath import scriptpath
print scriptpath()
~/python>./c
/home/bgolemon/python/sym/bar.py
~/python>./sym/bar.py
/home/bgolemon/python/sym/bar.py
~/python>./foo.py
/home/bgolemon/python/sym/bar.py
~/python>python/home/bgolemon/python/sym/bar.py
~/python>cd sym/
~/python/sym>python/home/bgolemon/python/sym/bar.py
--Buck