How to get/set logical directory path in python
Asked Answered
M

2

10

In python is it possible to get or set a logical directory (as opposed to an absolute one).

For example if I have:

/real/path/to/dir

and I have

/linked/path/to/dir

linked to the same directory.

using os.getcwd and os.chdir will always use the absolute path

>>> import os
>>> os.chdir('/linked/path/to/dir')
>>> print os.getcwd()
/real/path/to/dir

The only way I have found to get around this at all is to launch 'pwd' in another process and read the output. However, this only works until you call os.chdir for the first time.

Mesopotamia answered 23/9, 2008 at 21:19 Comment(0)
A
13

The underlying operational system / shell reports real paths to python.

So, there really is no way around it, since os.getcwd() is a wrapped call to C Library getcwd() function.

There are some workarounds in the spirit of the one that you already know which is launching pwd.

Another one would involve using os.environ['PWD']. If that environmnent variable is set you can make some getcwd function that respects it.

The solution below combines both:

import os
from subprocess import Popen, PIPE

class CwdKeeper(object):
    def __init__(self):
        self._cwd = os.environ.get("PWD")
        if self._cwd is None: # no environment. fall back to calling pwd on shell
           self._cwd = Popen('pwd', stdout=PIPE).communicate()[0].strip()
        self._os_getcwd = os.getcwd
        self._os_chdir = os.chdir

    def chdir(self, path):
        if not self._cwd:
            return self._os_chdir(path)
        p = os.path.normpath(os.path.join(self._cwd, path))
        result = self._os_chdir(p)
        self._cwd = p
        os.environ["PWD"] = p
        return result

    def getcwd(self):
        if not self._cwd:
            return self._os_getcwd()
        return self._cwd

cwd = CwdKeeper()
print cwd.getcwd()
# use only cwd.chdir and cwd.getcwd from now on.    
# monkeypatch os if you want:
os.chdir = cwd.chdir
os.getcwd = cwd.getcwd
# now you can use os.chdir and os.getcwd as normal.
Amoeba answered 23/9, 2008 at 21:19 Comment(0)
B
1

This also does the trick for me:

import os
os.popen('pwd').read().strip('\n')

Here is a demonstration in python shell:

>>> import os
>>> os.popen('pwd').read()
'/home/projteam/staging/site/proj\n'
>>> os.popen('pwd').read().strip('\n')
'/home/projteam/staging/site/proj'
>>> # Also works if PWD env var is set
>>> os.getenv('PWD')
'/home/projteam/staging/site/proj'
>>> # This gets actual path, not symlinked path
>>> import subprocess
>>> p = subprocess.Popen('pwd', stdout=subprocess.PIPE)
>>> p.communicate()[0]  # returns non-symlink path
'/home/projteam/staging/deploys/20150114-141114/site/proj\n'

Getting the environment variable PWD didn't always work for me so I use the popen method. Cheers!

Bullpen answered 14/1, 2015 at 20:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.