如何在Python3中计算根相对路径?

时间:2018-10-26 02:27:00

标签: python path relative-path

任务是实现功能root_relative_path(root : str, path : str) -> str,该功能计算相对于根的相对路径,而中间的..不会超出root。例如root_relative_path('/abc', '/../def') == '/abc/def'

此问题与How to calculate relative path in Python?不同,因为在这种情况下,root_relative_path(root='/tmp/abc', path='/../def')应该返回/tmp/abc/def而不是/tmp/def

3 个答案:

答案 0 :(得分:1)

./ext_libs_test --gtest_filter=NAV_NC_0002_RouteController_Test*
./ext_libs_test --gtest_filter=IF1_LastDestination_Test*
./ext_libs_test --gtest_filter=NAV_NC_0029_TrafficInformationController_Test*
./ext_libs_test --gtest_filter=NAV_NC_0051_RouteMonitorListController_Test*
./ext_libs_test --gtest_filter=NAV_NC_0068_LocationInformationProvider_Test*
./ext_libs_test --gtest_filter=NAV_NC_0067_LearningRecordingController_Test*

答案 1 :(得分:1)

我能够使用posixpath和pathlib模块的组合来实现root_relative_path函数。结果是

  • 与平台无关(只要根路径对应于当前平台)
  • 路径可以以/./../开头
  • 然后将使用normpath函数涵盖的所有技术对路径进行规范化,其中包括解决..的问题。

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)

答案 2 :(得分:0)

如何?

from pathlib import Path

def get_relative_path(path_from: Path, path_to: Path) -> Path:
    """
    Calculate and return a relative path between the `path_from` and
    `path_to` paths. Both paths must be absolute paths!
    """
    if not (path_from.is_absolute() and path_to.is_absolute()):
        raise ValueError('One or both of the passed paths are not absolute.')
    items_from = path_from.parts
    items_to = path_to.parts
    while items_from[0] == items_to[0]:
        items_from = items_from[1:]
        items_to = items_to[1:]
    return Path(*('..' for x in range(1, len(items_from))), *items_to)