Как рассчитать корневой относительный путь в Python3? - PullRequest
0 голосов
/ 26 октября 2018

Задача состоит в том, чтобы реализовать функцию root_relative_path(root : str, path : str) -> str, которая вычисляет относительный путь относительно корня без промежуточных .. выходов за пределы root. например, root_relative_path('/abc', '/../def') == '/abc/def'

Этот вопрос отличается от Как вычислить относительный путь в Python? , потому что в этом случае root_relative_path(root='/tmp/abc', path='/../def') должно возвращать /tmp/abc/def вместо /tmp/def.

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Мне удалось реализовать вашу функцию root_relative_path, используя комбинацию модулей posixpath и pathlib.Результат -

  • Независимо от платформы (если корневой путь соответствует текущей платформе)
  • Путь может начинаться с /, ./ или ../
  • И путь будет нормализован с использованием всех техник, охватываемых функцией normpath , которая включает в себя разрешение .. s.

from pathlib import Path
import posixpath

def root_relative_path(root : str, path : str) -> str:
    ''' Calculates the relative path with respect to the root. 
        Any ".."s in the relative path will be resolved, 
        but not in a way that would cause the relative path to go beyond the root. '''

    # posixpath.normpath doesn't work as expected if the path doesn't start with a slash, so we make sure it does
    if not path.startswith('/'):
        path = '/' + path

    # The normalization process includes resolving any ".."s
    # we're only using posixpath for the relative portion of the path, the outcome will still be platform independent
    path = posixpath.normpath(path)

    # Remove the beginning slash so that we're not trying to join two absolute paths
    path = path[1:]

    joined = Path(root) / path

    # Per the OPs requirements the result needed to be a string,
    # But if you're allowed to use Pathlib objects, you could just return joined without converting it to a string
    return str(joined)
0 голосов
/ 26 октября 2018
import os.path

def root_relative_path(root : str, path : str) -> str:
    return (os.path.join(root,
        os.path.join(os.sep, os.path.normpath(path)).split(os.sep)[1:])))
...