"""Common operations on Posix pathnames.Instead of importing this module directly, import os and refer tothis module as os.path. The "os.path" name is an alias for thismodule on Posix systems; on other systems (e.g. Windows),os.path provides the same operations in a manner specific to thatplatform, and is an alias to another module (e.g. ntpath).Some of this can actually be useful on non-Posix systems too, e.g.for manipulation of the pathname component of URLs."""# Strings representing various path-related bits and pieces.# These are primarily for export; internally, they are hardcoded.# Should be set before imports for resolving cyclic dependency.curdir = '.'pardir = '..'extsep = '.'sep = '/'pathsep = ':'defpath = '/bin:/usr/bin'altsep = Nonedevnull = '/dev/null'import osimport sysimport statimport genericpathfrom genericpath import *__all__ = ["normcase","isabs","join","splitdrive","split","splitext","basename","dirname","commonprefix","getsize","getmtime","getatime","getctime","islink","exists","lexists","isdir","isfile","ismount", "expanduser","expandvars","normpath","abspath","samefile","sameopenfile","samestat","curdir","pardir","sep","pathsep","defpath","altsep","extsep","devnull","realpath","supports_unicode_filenames","relpath","commonpath"]def _get_sep(path):if isinstance(path, bytes):return b'/'else:return '/'# Normalize the case of a pathname. Trivial in Posix, string.lower on Mac.# On MS-DOS this may also turn slashes into backslashes; however, other# normalizations (such as optimizing '../' away) are not allowed# (another function should be defined to do that).def normcase(s):"""Normalize case of pathname. Has no effect under Posix"""return os.fspath(s)# Return whether a path is absolute.# Trivial in Posix, harder on the Mac or MS-DOS.def isabs(s):"""Test whether a path is absolute"""s = os.fspath(s)sep = _get_sep(s)return s.startswith(sep)# Join pathnames.# Ignore the previous parts if a part is absolute.# Insert a '/' unless the first part is empty or already ends in '/'.def join(a, *p):"""Join two or more pathname components, inserting '/' as needed.If any component is an absolute path, all previous path componentswill be discarded. An empty last part will result in a path thatends with a separator."""a = os.fspath(a)sep = _get_sep(a)path = atry:if not p:path[:0] + sep #23780: Ensure compatible data type even if p is null.for b in map(os.fspath, p):if b.startswith(sep):path = belif not path or path.endswith(sep):path += belse:path += sep + bexcept (TypeError, AttributeError, BytesWarning):genericpath._check_arg_types('join', a, *p)raisereturn path# Split a path in head (everything up to the last '/') and tail (the# rest). If the path ends in '/', tail will be empty. If there is no# '/' in the path, head will be empty.# Trailing '/'es are stripped from head unless it is the root.def split(p):"""Split a pathname. Returns tuple "(head, tail)" where "tail" iseverything after the final slash. Either part may be empty."""p = os.fspath(p)sep = _get_sep(p)i = p.rfind(sep) + 1head, tail = p[:i], p[i:]if head and head != sep*len(head):head = head.rstrip(sep)return head, tail# Split a path in root and extension.# The extension is everything starting at the last dot in the last# pathname component; the root is everything before that.# It is always true that root + ext == p.def splitext(p):p = os.fspath(p)if isinstance(p, bytes):sep = b'/'extsep = b'.'else:sep = '/'extsep = '.'return genericpath._splitext(p, sep, None, extsep)splitext.__doc__ = genericpath._splitext.__doc__# Split a pathname into a drive specification and the rest of the# path. Useful on DOS/Windows/NT; on Unix, the drive is always empty.def splitdrive(p):"""Split a pathname into drive and path. On Posix, drive is alwaysempty."""p = os.fspath(p)return p[:0], p# Return the tail (basename) part of a path, same as split(path)[1].def basename(p):"""Returns the final component of a pathname"""p = os.fspath(p)sep = _get_sep(p)i = p.rfind(sep) + 1return p[i:]# Return the head (dirname) part of a path, same as split(path)[0].def dirname(p):"""Returns the directory component of a pathname"""p = os.fspath(p)sep = _get_sep(p)i = p.rfind(sep) + 1head = p[:i]if head and head != sep*len(head):head = head.rstrip(sep)return head# Is a path a symbolic link?# This will always return false on systems where os.lstat doesn't exist.def islink(path):"""Test whether a path is a symbolic link"""try:st = os.lstat(path)except (OSError, ValueError, AttributeError):return Falsereturn stat.S_ISLNK(st.st_mode)# Being true for dangling symbolic links is also useful.def lexists(path):"""Test whether a path exists. Returns True for broken symbolic links"""try:os.lstat(path)except (OSError, ValueError):return Falsereturn True# Is a path a mount point?# (Does this work for all UNIXes? Is it even guaranteed to work by Posix?)def ismount(path):"""Test whether a path is a mount point"""try:s1 = os.lstat(path)except (OSError, ValueError):# It doesn't exist -- so not a mount point. :-)return Falseelse:# A symlink can never be a mount pointif stat.S_ISLNK(s1.st_mode):return Falseif isinstance(path, bytes):parent = join(path, b'..')else:parent = join(path, '..')parent = realpath(parent)try:s2 = os.lstat(parent)except (OSError, ValueError):return Falsedev1 = s1.st_devdev2 = s2.st_devif dev1 != dev2:return True # path/.. on a different device as pathino1 = s1.st_inoino2 = s2.st_inoif ino1 == ino2:return True # path/.. is the same i-node as pathreturn False# Expand paths beginning with '~' or '~user'.# '~' means $HOME; '~user' means that user's home directory.# If the path doesn't begin with '~', or if the user or $HOME is unknown,# the path is returned unchanged (leaving error reporting to whatever# function is called with the expanded path as argument).# See also module 'glob' for expansion of *, ? and [...] in pathnames.# (A function should also be defined to do full *sh-style environment# variable expansion.)def expanduser(path):"""Expand ~ and ~user constructions. If user or $HOME is unknown,do nothing."""path = os.fspath(path)if isinstance(path, bytes):tilde = b'~'else:tilde = '~'if not path.startswith(tilde):return pathsep = _get_sep(path)i = path.find(sep, 1)if i < 0:i = len(path)if i == 1:if 'HOME' not in os.environ:import pwdtry:userhome = pwd.getpwuid(os.getuid()).pw_direxcept KeyError:# bpo-10496: if the current user identifier doesn't exist in the# password database, return the path unchangedreturn pathelse:userhome = os.environ['HOME']else:import pwdname = path[1:i]if isinstance(name, bytes):name = str(name, 'ASCII')try:pwent = pwd.getpwnam(name)except KeyError:# bpo-10496: if the user name from the path doesn't exist in the# password database, return the path unchangedreturn pathuserhome = pwent.pw_dirif isinstance(path, bytes):userhome = os.fsencode(userhome)root = b'/'else:root = '/'userhome = userhome.rstrip(root)return (userhome + path[i:]) or root# Expand paths containing shell variable substitutions.# This expands the forms $variable and ${variable} only.# Non-existent variables are left unchanged._varprog = None_varprogb = Nonedef expandvars(path):"""Expand shell variables of form $var and ${var}. Unknown variablesare left unchanged."""path = os.fspath(path)global _varprog, _varprogbif isinstance(path, bytes):if b'$' not in path:return pathif not _varprogb:import re_varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII)search = _varprogb.searchstart = b'{'end = b'}'environ = getattr(os, 'environb', None)else:if '$' not in path:return pathif not _varprog:import re_varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII)search = _varprog.searchstart = '{'end = '}'environ = os.environi = 0while True:m = search(path, i)if not m:breaki, j = m.span(0)name = m.group(1)if name.startswith(start) and name.endswith(end):name = name[1:-1]try:if environ is None:value = os.fsencode(os.environ[os.fsdecode(name)])else:value = environ[name]except KeyError:i = jelse:tail = path[j:]path = path[:i] + valuei = len(path)path += tailreturn path# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.# It should be understood that this may change the meaning of the path# if it contains symbolic links!def normpath(path):"""Normalize path, eliminating double slashes, etc."""path = os.fspath(path)if isinstance(path, bytes):sep = b'/'empty = b''dot = b'.'dotdot = b'..'else:sep = '/'empty = ''dot = '.'dotdot = '..'if path == empty:return dotinitial_slashes = path.startswith(sep)# POSIX allows one or two initial slashes, but treats three or more# as single slash.if (initial_slashes andpath.startswith(sep*2) and not path.startswith(sep*3)):initial_slashes = 2comps = path.split(sep)new_comps = []for comp in comps:if comp in (empty, dot):continueif (comp != dotdot or (not initial_slashes and not new_comps) or(new_comps and new_comps[-1] == dotdot)):new_comps.append(comp)elif new_comps:new_comps.pop()comps = new_compspath = sep.join(comps)if initial_slashes:path = sep*initial_slashes + pathreturn path or dotdef abspath(path):"""Return an absolute path."""path = os.fspath(path)if not isabs(path):if isinstance(path, bytes):cwd = os.getcwdb()else:cwd = os.getcwd()path = join(cwd, path)return normpath(path)# Return a canonical path (i.e. the absolute location of a file on the# filesystem).def realpath(filename):"""Return the canonical path of the specified filename, eliminating anysymbolic links encountered in the path."""filename = os.fspath(filename)path, ok = _joinrealpath(filename[:0], filename, {})return abspath(path)# Join two paths, normalizing and eliminating any symbolic links# encountered in the second path.def _joinrealpath(path, rest, seen):if isinstance(path, bytes):sep = b'/'curdir = b'.'pardir = b'..'else:sep = '/'curdir = '.'pardir = '..'if isabs(rest):rest = rest[1:]path = sepwhile rest:name, _, rest = rest.partition(sep)if not name or name == curdir:# current dircontinueif name == pardir:# parent dirif path:path, name = split(path)if name == pardir:path = join(path, pardir, pardir)else:path = pardircontinuenewpath = join(path, name)if not islink(newpath):path = newpathcontinue# Resolve the symbolic linkif newpath in seen:# Already seen this pathpath = seen[newpath]if path is not None:# use cached valuecontinue# The symlink is not resolved, so we must have a symlink loop.# Return already resolved part + rest of the path unchanged.return join(newpath, rest), Falseseen[newpath] = None # not resolved symlinkpath, ok = _joinrealpath(path, os.readlink(newpath), seen)if not ok:return join(path, rest), Falseseen[newpath] = path # resolved symlinkreturn path, Truesupports_unicode_filenames = (sys.platform == 'darwin')def relpath(path, start=None):"""Return a relative version of a path"""if not path:raise ValueError("no path specified")path = os.fspath(path)if isinstance(path, bytes):curdir = b'.'sep = b'/'pardir = b'..'else:curdir = '.'sep = '/'pardir = '..'if start is None:start = curdirelse:start = os.fspath(start)try:start_list = [x for x in abspath(start).split(sep) if x]path_list = [x for x in abspath(path).split(sep) if x]# Work out how much of the filepath is shared by start and path.i = len(commonprefix([start_list, path_list]))rel_list = [pardir] * (len(start_list)-i) + path_list[i:]if not rel_list:return curdirreturn join(*rel_list)except (TypeError, AttributeError, BytesWarning, DeprecationWarning):genericpath._check_arg_types('relpath', path, start)raise# Return the longest common sub-path of the sequence of paths given as input.# The paths are not normalized before comparing them (this is the# responsibility of the caller). Any trailing separator is stripped from the# returned path.def commonpath(paths):"""Given a sequence of path names, returns the longest common sub-path."""if not paths:raise ValueError('commonpath() arg is an empty sequence')paths = tuple(map(os.fspath, paths))if isinstance(paths[0], bytes):sep = b'/'curdir = b'.'else:sep = '/'curdir = '.'try:split_paths = [path.split(sep) for path in paths]try:isabs, = set(p[:1] == sep for p in paths)except ValueError:raise ValueError("Can't mix absolute and relative paths") from Nonesplit_paths = [[c for c in s if c and c != curdir] for s in split_paths]s1 = min(split_paths)s2 = max(split_paths)common = s1for i, c in enumerate(s1):if c != s2[i]:common = s1[:i]breakprefix = sep if isabs else sep[:0]return prefix + sep.join(common)except (TypeError, AttributeError):genericpath._check_arg_types('commonpath', *paths)raise
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。