Issue
I'm getting a nonsymetric behavior when using Path.relative_to
versus os.path.relpath
, see examples below. In Correspondence to tools in the os module, I was guided to believe they behave the same.
I'm working with two paths here
C:\Sync\Rmaster_head_\bin
C:\Sync\installed
I'm using Python 3.9.15.
os.path.relpath
>>> import os.path
>>> import pathlib
>>> start = pathlib.Path(r"../../installed")
>>> rel_path = os.path.relpath(pathlib.Path(r"C:/Sync/Rmaster_head_/bin"), start=start)
>>> rel_path
'..\\..\\..\\..\\Sync\\Rmaster_head_\\bin'
>>> start / pathlib.Path(rel_path)
WindowsPath('../../installed/../../../../Sync/Rmaster_head_/bin')
>>> (start / pathlib.Path(rel_path)).resolve()
WindowsPath('C:/Sync/Rmaster_head_/bin')
pathlib.Path.relative_to in both directions
>>> pathlib.Path(r"C:/Sync/Rmaster_head_/bin").relative_to(pathlib.Path(r"../../installed"))
Traceback (most recent call last):
File "C:\Sync\installed\R2023.1.175_install\sys\python3\x86_64-unknown-winnt_i19v19\lib\code.py", line 90, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
File "C:\Sync\installed\R2023.1.175_install\sys\python3\x86_64-unknown-winnt_i19v19\lib\pathlib.py", line 939, in relative_to
raise ValueError("{!r} is not in the subpath of {!r}"
ValueError: 'C:\\Sync\\Rmaster_head_\\bin' is not in the subpath of '..\\..\\installed' OR one path is relative and the other is absolute.
>>> pathlib.Path(r"../../installed").relative_to(pathlib.Path(r"C:/Sync/Rmaster_head_/bin"))
Traceback (most recent call last):
File "C:\Sync\installed\R2023.1.175_install\sys\python3\x86_64-unknown-winnt_i19v19\lib\code.py", line 90, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
File "C:\Sync\installed\R2023.1.175_install\sys\python3\x86_64-unknown-winnt_i19v19\lib\pathlib.py", line 939, in relative_to
raise ValueError("{!r} is not in the subpath of {!r}"
ValueError: '..\\..\\installed' is not in the subpath of 'C:\\Sync\\Rmaster_head_\\bin' OR one path is relative and the other is absolute.
I've noticed that the exception says that one of the paths is relative, but it doesn't also work when using full paths.
>>> path1 = pathlib.Path(r"C:\Sync\Rmaster_head_\bin")
>>> path2 = pathlib.Path(r"C:\Sync\installed\R2023.1.175_install\documentation")
>>> os.path.relpath(path1, start=path2)
'..\\..\\..\\Rmaster_head_\\bin'
>>> os.path.relpath(path2, start=path1)
'..\\..\\installed\\R2023.1.175_install\\documentation'
and path1.relative_to(path2)
and path2.relative_to(path1)
both fail.
What am I missing?
Solution
What you're missing is the notes about these methods in the pathlib documentation:
Below the documentation of relative_to()
:
NOTE: This function is part of
PurePath
and works with strings. It does not check or access the underlying file structure.
Although it would still be possible to derive the relative path you're looking for based on strings, apparently the method doesn't do that. The example and the error message are clear about this.
That the function is different than os.path.relpath()
is also explicitly mentions at the top of the section you mentioned in your question:
Note: Although
os.path.relpath()
andPurePath.relative_to()
have some overlapping use-cases, their semantics differ enough to warrant not considering them equivalent.
Unfortunately, this (along with some other things) means that pathlib
cannot be used to fully replace the os
functions. In many cases you'll have to use a mix of both :(
Answered By - wovano
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.