Domanda

In python è possibile ottenere o impostare una directory logica (al contrario di una assoluta).

Ad esempio se ho:

/real/path/to/dir

e ho

/linked/path/to/dir

collegato alla stessa directory.

usando os.getcwd e os.chdir userà sempre il percorso assoluto

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

L'unico modo in cui ho trovato di aggirare questo è di avviare 'pwd' in un altro processo e leggere l'output. Tuttavia, questo funziona solo fino a quando non si chiama os.chdir per la prima volta.

È stato utile?

Soluzione

Il sistema operativo / shell sottostante riporta percorsi reali a Python.

Quindi, non c'è davvero modo di evitarlo, dal momento che os.getcwd () è una chiamata chiusa alla funzione getcwd () della libreria C.

Esistono alcune soluzioni alternative nello spirito di quella che già conosci che sta lanciando pwd .

Un altro implicherebbe l'utilizzo di os.environ ['PWD'] . Se è impostata quella variabile di ambiente, è possibile eseguire una funzione getcwd che la rispetti.

La soluzione seguente combina entrambi:

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.

Altri suggerimenti

Anche questo fa il trucco per me:

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

Ecco una dimostrazione nella shell di Python:

>>> 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'

Ottenere la variabile d'ambiente PWD non ha sempre funzionato per me, quindi uso il metodo popen. Cheers!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top