如何计算Python3中的根相对路径?
how to calculate root relative path in Python3?
任务是实现一个函数root_relative_path(root : str, path : str) -> str
,它计算相对于根的相对路径,没有中间..
超出root
。例如,root_relative_path('/abc', '/../def') == '/abc/def'
这个问题不同于,因为在这种情况下,root_relative_path(root='/tmp/abc', path='/../def')
应该return /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 功能。结果是
- 平台无关(只要根路径对应当前平台即可)
- 路径可以以
/
、./
或 ../
开头
- 并且将使用 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)
这个怎么样:
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)
任务是实现一个函数root_relative_path(root : str, path : str) -> str
,它计算相对于根的相对路径,没有中间..
超出root
。例如,root_relative_path('/abc', '/../def') == '/abc/def'
这个问题不同于root_relative_path(root='/tmp/abc', path='/../def')
应该return /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 功能。结果是
- 平台无关(只要根路径对应当前平台即可)
- 路径可以以
/
、./
或../
开头
- 并且将使用 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)
这个怎么样:
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)