Easier way to get the "here" path?

B

bukzor

I have to go into these convulsions to get the directory that the
script is in whenever I need to use relative paths. I was wondering if
you guys have a better way:

from os.path import dirname, realpath, abspath
here = dirname(realpath(abspath(__file__.rstrip("c"))))

In particular, this takes care of the case of symlinked, compiled
scripts, which is fairly common at my workplace, and I imagine in many
*nix evironments.


An illustration:
$echo "print __file__" > symlinks/path.py
$ln -s symlinks/path.py
$python
'/home/bgolemon/python/symlinks/symlinks/path.py'
 
A

Andrew

bukzor said:
I have to go into these convulsions to get the directory that the
script is in whenever I need to use relative paths. I was wondering if
you guys have a better way:
...
If you just need the current path (where it is executed) why not use
os.getcwd()
which returns a string of the absolute path to the module being executed.


$ echo "print __file__" > path.py
$ ipython
In [1]: import path
path.pyc

In [2]: import os

In [3]: os.path.join(os.getcwd(), path.__file__.rstrip("c"))
Out[3]: '/home/andrew/path.py'
 
A

Andrew

bukzor said:
'/home/bgolemon/python/symlinks/symlinks/path.py'
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
 
M

MRAB

I have to go into these convulsions to get the directory that the
script is in whenever I need to use relative paths. I was wondering if
you guys have a better way:

from os.path import dirname, realpath, abspath
here = dirname(realpath(abspath(__file__.rstrip("c"))))

In particular, this takes care of the case of symlinked, compiled
scripts, which is fairly common at my workplace, and I imagine in many
*nix evironments.

An illustration:
$echo "print __file__" > symlinks/path.py
$ln -s symlinks/path.py
$python>>> import path
path.py

'/home/bgolemon/python/symlinks/path.py'>>> realpath(abspath(path.__file__.rstrip("c")))

'/home/bgolemon/python/symlinks/symlinks/path.py'

How about:

import os
import sys
here = os.path.realpath(os.path.dirname(sys.argv[0]))

It's a little clearer. :)
 
A

Andrew

Andrew said:
bukzor said:
I have to go into these convulsions to get the directory that the
script is in whenever I need to use relative paths. I was wondering if
you guys have a better way:
...
If you just need the current path (where it is executed) why not use
os.getcwd()
which returns a string of the absolute path to the module being executed.


$ echo "print __file__" > path.py
$ ipython
In [1]: import path
path.pyc

In [2]: import os

In [3]: os.path.join(os.getcwd(), path.__file__.rstrip("c"))
Out[3]: '/home/andrew/path.py'
I was thinking of this in the module being imported, but now that I try,
it doesn't work. It is still seeing itself from the symlink's position.

This works, in the module being imported:
$ less path.py
from os.path import realpath
here = realpath(__file__.rstrip("c"))

$ python'/home/andrew/sym/sym/path.py'
 
B

bukzor

bukzor said:
'/home/bgolemon/python/symlinks/symlinks/path.py'

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?
 
B

bukzor

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top