classification
Title: pathlib behave differ between OS
Type: behavior Stage: resolved
Components: FreeBSD, macOS, Windows Versions: Python 3.8, Python 3.7, Python 3.6
process
Status: closed Resolution: duplicate
Dependencies: Superseder: pathlib.Path.resolve(strict=False) returns relative path on Windows if the entry does not exist
View: 38671
Assigned To: Nosy List: Mond Wan, koobs, ned.deily, paul.moore, ronaldoussoren, steve.dower, tim.golden, zach.ware
Priority: normal Keywords:

Created on 2020-07-31 09:28 by Mond Wan, last changed 2020-07-31 14:24 by eryksun. This issue is now closed.

Messages (6)
msg374632 - (view) Author: Mond Wan (Mond Wan) Date: 2020-07-31 09:28
I have tried 2 functions with different behavior across platform

# as_posix()

In linux platform, as_posix() cannot process window path nicely

* From linux + docker + python:3.8

```
Python 3.8.0 (default, Oct 17 2019, 05:36:36)
[GCC 8.3.0] on linux

>>> winPath = r'\workspace\xxx\test_fixture\user-restore-success.zip'
>>> posixPath = '/workspace/xxx/test_fixture/user-restore-success.zip'
>>> pWIN = pathlib.PurePath(winPath)
>>> pPOSIX = pathlib.PurePath(posixPath)
>>> pWIN.as_posix()
'\\workspace\\xxx\\test_fixture\\user-restore-success.zip'
>>> pPOSIX.as_posix()
'/workspace/xxx/test_fixture/user-restore-success.zip'
```

* From window + powershell + python3.6

```
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32

>>> winPath = r'\workspace\xxx\test_fixture\user-restore-success.zip'
>>> posixPath = '/workspace/xxx/test_fixture/user-restore-success.zip'
>>> pWIN = pathlib.PurePath(winPath)
>>> pPOSIX = pathlib.PurePath(posixPath)
>>> pWIN.as_posix()
'/workspace/xxx/test_fixture/user-restore-success.zip'
>>> pPOSIX.as_posix()
'/workspace/xxx/test_fixture/user-restore-success.zip'

```

* From MAC

```
>>> winPath = '\\workspace\\xxx\\test_fixture\\user-restore-success.zip'
>>> posixPath = '/workspace/xxx/test_fixture/user-restore-success.zip'
>>> pWIN = pathlib.PurePath(winPath)
>>> pPOSIX = pathlib.PurePath(posixPath)
>>> pWIN.as_posix()
'\\workspace\\xxx\\test_fixture\\user-restore-success.zip'
>>> pPOSIX.as_posix()
'/workspace/xxx/test_fixture/user-restore-success.zip'
```

# resolve()

In window platform, resolve() returns absolute path only if such file is able to locate. Otherwise, it returns
relative path.

In Linux platform, resolve() returns absolute path anyway

* From linux

```
b4f03ed3003b">root@b4f03ed3003b:/var/run/lock# python
Python 3.8.0 (default, Oct 17 2019, 05:36:36)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pathlib
>>> p = pathlib.Path('no_exists')
>>> p.resolve()
PosixPath('/run/lock/no_exists')
>>> str(p.resolve())
'/run/lock/no_exits'

```

* From window

```
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pathlib
>>> p = pathlib.Path('README.md')
>>> p.resolve()
WindowsPath('C:/Users/xxx/PycharmProjects/yyy/README.md')
>>> str(p.resolve())
'C:\\Users\\xxx\\PycharmProjects\\yyy\\README.md'
>>> p = pathlib.Path('no_exists')
>>> p.resolve()
WindowsPath('no_exists')
>>> str(p.resolve())
'no_exists'

```

Also, I have spotted a ticket similar to this one

https://bugs.python.org/issue41357
msg374635 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2020-07-31 10:56
I'm not sure what you try to report.

PurePath(...) returns a PureWindowsPath on Windows and an PurePosixPath on other (unix-y) platforms. This explains the difference in behaviour you're seeing for as_posix().
msg374637 - (view) Author: Mond Wan (Mond Wan) Date: 2020-07-31 11:19
Let me clarify my expectation.

# For `as_posix()`

* PureWindowsPath can translate both POSIX path, and WINDOW path to POSIX path via `as_posix()`
    * Therefore, I expect PurePosixPath can translate both platform path to POSIX path via `as_posix()`

* I just tried PurePosixPath() behave same between Window, and the docker.
    * I am sorry for showing misleading information

# For `resolve()`

* In window platform, resolve() returns absolute path only if such file is able to locate. Otherwise, it returns
relative path.

* In Linux platform, resolve() returns absolute path anyway
msg374638 - (view) Author: Mond Wan (Mond Wan) Date: 2020-07-31 11:27
Moreover, output from PurePosixPath.as_posix() is not that straightforward?

Please take a look below example from python3.6 + linux + docker

```
>>> winPath = r'\workspace\xxx\test_fixture\user-restore-success.zip'

>>> pWIN = pathlib.PureWindowsPath(winPath)
>>> pppFromWinPath = pathlib.PurePosixPath(winPath)
>>> pppFromPwp = pathlib.PurePosixPath(pWIN)

>>> pppFromWinPath.as_posix()
'\\workspace\\xxx\\test_fixture\\user-restore-success.zip'
>>> pppFromPwp.as_posix()
'\\/workspace/xxx/test_fixture/user-restore-success.zip'
```

* Construction PurePosixPath from rawString, `as_posix()` gives '\\workspace\\xxx\\test_fixture\\user-restore-success.zip'
* Construction PurePosixPath from PureWindowsPath, `as_posix()` gives '\\/workspace/xxx/test_fixture/user-restore-success.zip'
msg374639 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2020-07-31 12:06
PureWindowsPath does not know about POSIX paths, it supports the two styles of directory separator that are valid on Windows: '/' and '\'. 

PurePosixPath only supports the single stile of directory separator valid on POSIX systems: '/'. 

On a Posix system backslash is a valid character in a file name and is NOT a directory separator.


The behaviour of Path.resolve() on Windows may or may not be a bug, the documentation is not quite clear. Personally I'd lean toward saying this is a bug, but I defer to a pathlib expert.  Note that path.resolve(strict=True) should raise an error on both platforms when the path does not exists.
msg374640 - (view) Author: Mond Wan (Mond Wan) Date: 2020-07-31 12:47
Thanks for the clarifications on PurePosixPath(). Now, I know which library I should use to solve my problem.

For resolve() with strict True, I have tried on both platform. They will both raise exception if that file does not exists.
History
Date User Action Args
2020-07-31 14:24:54eryksunsetstatus: open -> closed
superseder: pathlib.Path.resolve(strict=False) returns relative path on Windows if the entry does not exist
resolution: duplicate
stage: resolved
2020-07-31 12:47:01Mond Wansetmessages: + msg374640
2020-07-31 12:06:15ronaldoussorensetmessages: + msg374639
2020-07-31 11:27:58Mond Wansetmessages: + msg374638
2020-07-31 11:19:42Mond Wansetmessages: + msg374637
2020-07-31 10:56:20ronaldoussorensetmessages: + msg374635
2020-07-31 09:30:00Mond Wansettype: behavior
2020-07-31 09:28:44Mond Wancreate