Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

normalize non-existing path using pathlib only

python has recently added the pathlib module (which i like a lot!).

there is just one thing i'm struggling with: is it possible to normalize a path to a file or directory that does not exist? i can do that perfectly well with os.path.normpath. but wouldn't it be absurd to have to use something other than the library that should take care of path related stuff?

the functionality i would like to have is this:

from os.path import normpath
from pathlib import Path
pth = Path('/tmp/some_directory/../i_do_not_exist.txt')
pth = Path(normpath(str(pth)))
# -> /tmp/i_do_not_exist.txt

but without having to resort to os.path and without having to type-cast to str and back to Path. also pth.resolve() does not work for non-existing files.

is there a simple way to do that with just pathlib?

like image 894
hiro protagonist Avatar asked Sep 02 '15 16:09

hiro protagonist


People also ask

What does Pathlib path () do?

The pathlib is a Python module which provides an object API for working with files and directories. The pathlib is a standard module. Path is the core object to work with files.

How do you get path from PosixPath?

Python Path and PosixPath: How to get the current path of a file or directory. In Python, pathlib package is very useful and helpful to get the file/directory path. First, import Path from pathlib . The path of the current file is Path(__file__) but it is an object (and the type of it is PosixPath).

What does Pathlib path return?

parts : returns a tuple that provides access to the path's components. name : the path component without any directory. parent : sequence providing access to the logical ancestors of the path. stem : final path component without its suffix.

Is Pathlib path PathLike?

pathlib. Path (WindowsPath, PosixPath, etc.) objects are not considered PathLike : PY-30747.


3 Answers

is it possible to normalize a path to a file or directory that does not exist?

Starting from 3.6, it's the default behavior. See https://docs.python.org/3.6/library/pathlib.html#pathlib.Path.resolve

Path.resolve(strict=False)
...
If strict is False, the path is resolved as far as possible and any remainder is appended without checking whether it exists

like image 115
ento Avatar answered Sep 21 '22 03:09

ento


As of Python 3.5: No, there's not.

PEP 0428 states:

Path resolution

The resolve() method makes a path absolute, resolving any symlink on the way (like the POSIX realpath() call). It is the only operation which will remove " .. " path components. On Windows, this method will also take care to return the canonical path (with the right casing).

Since resolve() is the only operation to remove the ".." components, and it fails when the file doesn't exist, there won't be a simple means using just pathlib.

Also, the pathlib documentation gives a hint as to why:

Spurious slashes and single dots are collapsed, but double dots ('..') are not, since this would change the meaning of a path in the face of symbolic links:

PurePath('foo//bar') produces PurePosixPath('foo/bar')

PurePath('foo/./bar') produces PurePosixPath('foo/bar')

PurePath('foo/../bar') produces PurePosixPath('foo/../bar')

(a naïve approach would make PurePosixPath('foo/../bar') equivalent to PurePosixPath('bar'), which is wrong if foo is a symbolic link to another directory)

All that said, you could create a 0 byte file at the location of your path, and then it'd be possible to resolve the path (thus eliminating the ..). I'm not sure that's any simpler than your normpath approach, though.

like image 23
Bryant Avatar answered Sep 20 '22 03:09

Bryant


If this fits you usecase(e.g. ifle's directory already exists) you might try to resolve path's parent and then re-append file name, e.g.:

from pathlib import Path

p = Path()/'hello.there'
print(p.parent.resolve()/p.name)
like image 24
kerim Avatar answered Sep 17 '22 03:09

kerim