If you're looking for a built-in or stdlib function that does exactly what you want, there is none.
If you're looking for a third-party library, try searching PyPI and ActiveState. You'll find path-manipulation libraries like pathlib
(that has been included since Python 3.4), Unipath
and forked-path
(both based on an earlier library, a modified version of which was considered but never accepted for inclusion in Python 2), and dozens more. (Or, if you're using a framework like twisted
or PyQt
, it may come with one built in.)
Using such a library, you can generally get the root path in one line, like:
pathlib.Path(mypath).parts[0]
Unipath.Path(mypath).split_root()[0]
Unipath.Path(mypath).components()[0]
path.path(mypath).splitall()[0]
Their definition of "root" might not be exactly the same as yours. (As J.F. Sebastian points out, we don't actually know exactly what your definition of "root" is, so it's hard to guess whether it will match…) So, you might still need this kind of code:
components = path.path(mypath).splitall()[0]
return components[0] if len(components[0]) > 1 else components[0]/components[1]
But regardless, it'll be better than doing regexps and string manipulation.
(In fact, even if you don't use a third-party library, you should try to build everything out of os.path
functions instead of string functions—that way, when you try it on Windows next year, there's a good chance it'll work out of the box, and if not it'll probably require only minor changes, as opposed to being absolutely guaranteed it won't work and might need a complete rewrite.)
/
? – Fusibleos.path.join(os.path.sep, '/foo/bar/baz'.split(os.path.sep)[1])
? – Stengeros.path.dirname(os.path.dirname(x))
? Calling it "base" when that's the exact opposite of what "basename" usually means in POSIX (and Python, etc.) is a bit confusing. Even if arguably it's POSIX that was originally confusing, it's such standard practice by now that you shouldn't fight it. – Cumbrousfullsplit
that callsos.path.split
iteratively (or recursively) until it ends—and then this function is trivial (it'sparts[0]
oros.path.join(*parts[:2])
) instead of doing regexps and string functions. But I don't think you're going to get any simpler than that. – Cumbrouspath
module that was rejected for stdlib inclusion a few times (which I think is an ancestor of bothforkedpath
andUnipath
on PyPI, but I'm not sure) had aroot
that may or may not be what you want, and asplitall
that you can build what you want from trivially. – Cumbrous"foo"
,"./foo"
,"foo/"
,"/foo"
,"/foo/"
,"/foo/bar"
,"../bar"
,"/../bar"
(note: leading slash),"foo/../bar"
,"/"
(root directory),"."
,""
(it might mean current directory)? – Ume"foo/bar/baz".partition("/")[0]
works for this particular narrow case but it is not applicable to paths in general and I wouldn't recommend it. – Ume