Por que usar os dois, os.path.abspath e os.path.realpath?

98

Em vários projetos de código aberto, vi pessoas fazerem os.path.abspath(os.path.realpath(__file__))para obter o caminho absoluto para o arquivo atual.

No entanto, acho isso os.path.abspath(__file__)e os.path.realpath(__file__)produzo o mesmo resultado. os.path.abspath(os.path.realpath(__file__))parece ser um pouco redundante.

Existe uma razão para as pessoas estarem usando isso?

hch
fonte

Respostas:

66

os.path.realpath remove links simbólicos nos sistemas operacionais que os suportam.

os.path.abspathsimplesmente remove coisas como .e ..do caminho dando um caminho completo da raiz da árvore de diretórios para o arquivo nomeado (ou link simbólico)

Por exemplo, no Ubuntu

$ ls -l
total 0
-rw-rw-r-- 1 guest guest 0 Jun 16 08:36 a
lrwxrwxrwx 1 guest guest 1 Jun 16 08:36 b -> a

$ python
Python 2.7.11 (default, Dec 15 2015, 16:46:19) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.

>>> from os.path import abspath, realpath

>>> abspath('b')
'/home/guest/play/paths/b'

>>> realpath('b')
'/home/guest/play/paths/a'

Os links simbólicos podem conter caminhos relativos, daí a necessidade de usar ambos. A chamada interna para realpathpode retornar um caminho com ..partes incorporadas , que abspathentão são removidas.

kdopen
fonte
10
Embora essa resposta descreva a diferença entre as duas funções, não é verdade que o resultado de realpath()pode conter ..componentes e não responde realmente à pergunta de por que você usaria ambos; a resposta de jobrad é mais precisa.
Miles
Para Python 3.7 e Windows, o realpath não entende as unidades subestadas. Portanto, para uma unidade subestada, diga P: \, tendo a pasta de origem c: \ MyFolder \ Bla, realpath retorna P: \ não c: \ MyFolder \ Bla. Alguém sabe como pegar o caminho "real"?
Totte Karlsson
Para mim, abspathainda segue os links simbólicos se o diretório atual for um link simbólico. Eu só encontrei esta resposta stackoverflow.com/questions/54665065/… para interromper esse comportamento.
Victor Sergienko
107

Para o seu cenário declarado, não há razão para combinar realpath e abspath, uma vez que os.path.realpathrealmente chama os.path.abspathantes de retornar um resultado (eu verifiquei Python 2.5 para Python 3.6).

  • os.path.abspath retorna o caminho absoluto, mas NÃO resolve links simbólicos em seu argumento.
  • os.path.realpath primeiro resolverá quaisquer links simbólicos no caminho e, em seguida, retornará o caminho absoluto.

No entanto, se você espera que seu caminho contenha um ~, nem abspath nem realpath serão resolvidos ~para o diretório inicial do usuário e o caminho resultante será inválido . Você precisará usar os.path.expanduserpara resolver isso no diretório do usuário.

Para uma explicação completa, aqui estão alguns resultados que verifiquei no Windows e no Linux, no Python 3.4 e no Python 2.6. O diretório atual ( ./) é meu diretório inicial, que se parece com isto:

myhome
|- data (symlink to /mnt/data)
|- subdir (extra directory, for verbose explanation)
# os.path.abspath returns the absolute path, but does NOT resolve symlinks in its argument
os.path.abspath('./')
'/home/myhome'
os.path.abspath('./subdir/../data')
'/home/myhome/data'


# os.path.realpath will resolve symlinks AND return an absolute path from a relative path
os.path.realpath('./')
'/home/myhome'
os.path.realpath('./subdir/../')
'/home/myhome'
os.path.realpath('./subdir/../data')
'/mnt/data'

# NEITHER abspath or realpath will resolve or remove ~.
os.path.abspath('~/data')
'/home/myhome/~/data'

os.path.realpath('~/data')
'/home/myhome/~/data'

# And the returned path will be invalid
os.path.exists(os.path.abspath('~/data'))
False
os.path.exists(os.path.realpath('~/data'))
False

# Use realpath + expanduser to resolve ~
os.path.realpath(os.path.expanduser('~/subdir/../data'))
'/mnt/data'
Jobrad
fonte
3
Agradável. Para enfatizar, seu último exemplo deveria seros.path.realpath(os.path.expanduser('~/subdir/../data'))
Arthur,
3
Então também não se esqueça de os.path.expandvars se as variáveis ​​forem usadas em um caminho
Slavenskij
7

Em termos gerais, se você está tentando obter o caminho de um arquivo de atalho, caminho absoluto fornece o caminho completo do arquivo presente no local do atalho , enquanto realpath fornece o caminho do local original do arquivo.

Caminho absoluto, os.path.abspath (), fornece o caminho completo do arquivo que está localizado no diretório de trabalho atual ou no diretório que você mencionou.

Caminho real, os.path.realpath (), fornece o caminho completo do arquivo que está sendo referido.

Por exemplo:

file = "shortcut_folder/filename"
os.path.abspath(file) = "C:/Desktop/shortcut_folder/filename"
os.path.realpath(file) = "D:/PyCharmProjects/Python1stClass/filename"
ExtractTable.com
fonte