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



任务是实现一个函数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

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:])))

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

  • 独立于平台(只要根路径对应于当前平台(
  • 路径可以从/./../开始
  • 并且将使用包括解析..s的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)

这个怎么样:

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)

相关内容

  • 没有找到相关文章

最新更新