zoukankan      html  css  js  c++  java
  • python:OS模块

       1 r"""OS routines for NT or Posix depending on what system we're on.
       2 
       3 This exports:
       4   - all functions from posix or nt, e.g. unlink, stat, etc.
       5   - os.path is either posixpath or ntpath
       6   - os.name is either 'posix' or 'nt'
       7   - os.curdir is a string representing the current directory (always '.')
       8   - os.pardir is a string representing the parent directory (always '..')
       9   - os.sep is the (or a most common) pathname separator ('/' or '\')
      10   - os.extsep is the extension separator (always '.')
      11   - os.altsep is the alternate pathname separator (None or '/')
      12   - os.pathsep is the component separator used in $PATH etc
      13   - os.linesep is the line separator in text files ('
    ' or '
    ' or '
    ')
      14   - os.defpath is the default search path for executables
      15   - os.devnull is the file path of the null device ('/dev/null', etc.)
      16 
      17 Programs that import and use 'os' stand a better chance of being
      18 portable between different platforms.  Of course, they must then
      19 only use functions that are defined by all platforms (e.g., unlink
      20 and opendir), and leave all pathname manipulation to os.path
      21 (e.g., split and join).
      22 """
      23 
      24 #'
      25 import abc
      26 import sys, errno
      27 import stat as st
      28 
      29 _names = sys.builtin_module_names
      30 
      31 # Note:  more names are added to __all__ later.
      32 __all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep",
      33            "defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR",
      34            "SEEK_END", "fsencode", "fsdecode", "get_exec_path", "fdopen",
      35            "popen", "extsep"]
      36 
      37 def _exists(name):
      38     return name in globals()
      39 
      40 def _get_exports_list(module):
      41     try:
      42         return list(module.__all__)
      43     except AttributeError:
      44         return [n for n in dir(module) if n[0] != '_']
      45 
      46 # Any new dependencies of the os module and/or changes in path separator
      47 # requires updating importlib as well.
      48 if 'posix' in _names:
      49     name = 'posix'
      50     linesep = '
    '
      51     from posix import *
      52     try:
      53         from posix import _exit
      54         __all__.append('_exit')
      55     except ImportError:
      56         pass
      57     import posixpath as path
      58 
      59     try:
      60         from posix import _have_functions
      61     except ImportError:
      62         pass
      63 
      64     import posix
      65     __all__.extend(_get_exports_list(posix))
      66     del posix
      67 
      68 elif 'nt' in _names:
      69     name = 'nt'
      70     linesep = '
    '
      71     from nt import *
      72     try:
      73         from nt import _exit
      74         __all__.append('_exit')
      75     except ImportError:
      76         pass
      77     import ntpath as path
      78 
      79     import nt
      80     __all__.extend(_get_exports_list(nt))
      81     del nt
      82 
      83     try:
      84         from nt import _have_functions
      85     except ImportError:
      86         pass
      87 
      88 else:
      89     raise ImportError('no os specific module found')
      90 
      91 sys.modules['os.path'] = path
      92 from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep,
      93     devnull)
      94 
      95 del _names
      96 
      97 
      98 if _exists("_have_functions"):
      99     _globals = globals()
     100     def _add(str, fn):
     101         if (fn in _globals) and (str in _have_functions):
     102             _set.add(_globals[fn])
     103 
     104     _set = set()
     105     _add("HAVE_FACCESSAT",  "access")
     106     _add("HAVE_FCHMODAT",   "chmod")
     107     _add("HAVE_FCHOWNAT",   "chown")
     108     _add("HAVE_FSTATAT",    "stat")
     109     _add("HAVE_FUTIMESAT",  "utime")
     110     _add("HAVE_LINKAT",     "link")
     111     _add("HAVE_MKDIRAT",    "mkdir")
     112     _add("HAVE_MKFIFOAT",   "mkfifo")
     113     _add("HAVE_MKNODAT",    "mknod")
     114     _add("HAVE_OPENAT",     "open")
     115     _add("HAVE_READLINKAT", "readlink")
     116     _add("HAVE_RENAMEAT",   "rename")
     117     _add("HAVE_SYMLINKAT",  "symlink")
     118     _add("HAVE_UNLINKAT",   "unlink")
     119     _add("HAVE_UNLINKAT",   "rmdir")
     120     _add("HAVE_UTIMENSAT",  "utime")
     121     supports_dir_fd = _set
     122 
     123     _set = set()
     124     _add("HAVE_FACCESSAT",  "access")
     125     supports_effective_ids = _set
     126 
     127     _set = set()
     128     _add("HAVE_FCHDIR",     "chdir")
     129     _add("HAVE_FCHMOD",     "chmod")
     130     _add("HAVE_FCHOWN",     "chown")
     131     _add("HAVE_FDOPENDIR",  "listdir")
     132     _add("HAVE_FEXECVE",    "execve")
     133     _set.add(stat) # fstat always works
     134     _add("HAVE_FTRUNCATE",  "truncate")
     135     _add("HAVE_FUTIMENS",   "utime")
     136     _add("HAVE_FUTIMES",    "utime")
     137     _add("HAVE_FPATHCONF",  "pathconf")
     138     if _exists("statvfs") and _exists("fstatvfs"): # mac os x10.3
     139         _add("HAVE_FSTATVFS", "statvfs")
     140     supports_fd = _set
     141 
     142     _set = set()
     143     _add("HAVE_FACCESSAT",  "access")
     144     # Some platforms don't support lchmod().  Often the function exists
     145     # anyway, as a stub that always returns ENOSUP or perhaps EOPNOTSUPP.
     146     # (No, I don't know why that's a good design.)  ./configure will detect
     147     # this and reject it--so HAVE_LCHMOD still won't be defined on such
     148     # platforms.  This is Very Helpful.
     149     #
     150     # However, sometimes platforms without a working lchmod() *do* have
     151     # fchmodat().  (Examples: Linux kernel 3.2 with glibc 2.15,
     152     # OpenIndiana 3.x.)  And fchmodat() has a flag that theoretically makes
     153     # it behave like lchmod().  So in theory it would be a suitable
     154     # replacement for lchmod().  But when lchmod() doesn't work, fchmodat()'s
     155     # flag doesn't work *either*.  Sadly ./configure isn't sophisticated
     156     # enough to detect this condition--it only determines whether or not
     157     # fchmodat() minimally works.
     158     #
     159     # Therefore we simply ignore fchmodat() when deciding whether or not
     160     # os.chmod supports follow_symlinks.  Just checking lchmod() is
     161     # sufficient.  After all--if you have a working fchmodat(), your
     162     # lchmod() almost certainly works too.
     163     #
     164     # _add("HAVE_FCHMODAT",   "chmod")
     165     _add("HAVE_FCHOWNAT",   "chown")
     166     _add("HAVE_FSTATAT",    "stat")
     167     _add("HAVE_LCHFLAGS",   "chflags")
     168     _add("HAVE_LCHMOD",     "chmod")
     169     if _exists("lchown"): # mac os x10.3
     170         _add("HAVE_LCHOWN", "chown")
     171     _add("HAVE_LINKAT",     "link")
     172     _add("HAVE_LUTIMES",    "utime")
     173     _add("HAVE_LSTAT",      "stat")
     174     _add("HAVE_FSTATAT",    "stat")
     175     _add("HAVE_UTIMENSAT",  "utime")
     176     _add("MS_WINDOWS",      "stat")
     177     supports_follow_symlinks = _set
     178 
     179     del _set
     180     del _have_functions
     181     del _globals
     182     del _add
     183 
     184 
     185 # Python uses fixed values for the SEEK_ constants; they are mapped
     186 # to native constants if necessary in posixmodule.c
     187 # Other possible SEEK values are directly imported from posixmodule.c
     188 SEEK_SET = 0
     189 SEEK_CUR = 1
     190 SEEK_END = 2
     191 
     192 # Super directory utilities.
     193 # (Inspired by Eric Raymond; the doc strings are mostly his)
     194 
     195 def makedirs(name, mode=0o777, exist_ok=False):
     196     """makedirs(name [, mode=0o777][, exist_ok=False])
     197 
     198     Super-mkdir; create a leaf directory and all intermediate ones.  Works like
     199     mkdir, except that any intermediate path segment (not just the rightmost)
     200     will be created if it does not exist. If the target directory already
     201     exists, raise an OSError if exist_ok is False. Otherwise no exception is
     202     raised.  This is recursive.
     203 
     204     """
     205     head, tail = path.split(name)
     206     if not tail:
     207         head, tail = path.split(head)
     208     if head and tail and not path.exists(head):
     209         try:
     210             makedirs(head, mode, exist_ok)
     211         except FileExistsError:
     212             # Defeats race condition when another thread created the path
     213             pass
     214         cdir = curdir
     215         if isinstance(tail, bytes):
     216             cdir = bytes(curdir, 'ASCII')
     217         if tail == cdir:           # xxx/newdir/. exists if xxx/newdir exists
     218             return
     219     try:
     220         mkdir(name, mode)
     221     except OSError:
     222         # Cannot rely on checking for EEXIST, since the operating system
     223         # could give priority to other errors like EACCES or EROFS
     224         if not exist_ok or not path.isdir(name):
     225             raise
     226 
     227 def removedirs(name):
     228     """removedirs(name)
     229 
     230     Super-rmdir; remove a leaf directory and all empty intermediate
     231     ones.  Works like rmdir except that, if the leaf directory is
     232     successfully removed, directories corresponding to rightmost path
     233     segments will be pruned away until either the whole path is
     234     consumed or an error occurs.  Errors during this latter phase are
     235     ignored -- they generally mean that a directory was not empty.
     236 
     237     """
     238     rmdir(name)
     239     head, tail = path.split(name)
     240     if not tail:
     241         head, tail = path.split(head)
     242     while head and tail:
     243         try:
     244             rmdir(head)
     245         except OSError:
     246             break
     247         head, tail = path.split(head)
     248 
     249 def renames(old, new):
     250     """renames(old, new)
     251 
     252     Super-rename; create directories as necessary and delete any left
     253     empty.  Works like rename, except creation of any intermediate
     254     directories needed to make the new pathname good is attempted
     255     first.  After the rename, directories corresponding to rightmost
     256     path segments of the old name will be pruned until either the
     257     whole path is consumed or a nonempty directory is found.
     258 
     259     Note: this function can fail with the new directory structure made
     260     if you lack permissions needed to unlink the leaf directory or
     261     file.
     262 
     263     """
     264     head, tail = path.split(new)
     265     if head and tail and not path.exists(head):
     266         makedirs(head)
     267     rename(old, new)
     268     head, tail = path.split(old)
     269     if head and tail:
     270         try:
     271             removedirs(head)
     272         except OSError:
     273             pass
     274 
     275 __all__.extend(["makedirs", "removedirs", "renames"])
     276 
     277 def walk(top, topdown=True, onerror=None, followlinks=False):
     278     """Directory tree generator.
     279 
     280     For each directory in the directory tree rooted at top (including top
     281     itself, but excluding '.' and '..'), yields a 3-tuple
     282 
     283         dirpath, dirnames, filenames
     284 
     285     dirpath is a string, the path to the directory.  dirnames is a list of
     286     the names of the subdirectories in dirpath (excluding '.' and '..').
     287     filenames is a list of the names of the non-directory files in dirpath.
     288     Note that the names in the lists are just names, with no path components.
     289     To get a full path (which begins with top) to a file or directory in
     290     dirpath, do os.path.join(dirpath, name).
     291 
     292     If optional arg 'topdown' is true or not specified, the triple for a
     293     directory is generated before the triples for any of its subdirectories
     294     (directories are generated top down).  If topdown is false, the triple
     295     for a directory is generated after the triples for all of its
     296     subdirectories (directories are generated bottom up).
     297 
     298     When topdown is true, the caller can modify the dirnames list in-place
     299     (e.g., via del or slice assignment), and walk will only recurse into the
     300     subdirectories whose names remain in dirnames; this can be used to prune the
     301     search, or to impose a specific order of visiting.  Modifying dirnames when
     302     topdown is false is ineffective, since the directories in dirnames have
     303     already been generated by the time dirnames itself is generated. No matter
     304     the value of topdown, the list of subdirectories is retrieved before the
     305     tuples for the directory and its subdirectories are generated.
     306 
     307     By default errors from the os.scandir() call are ignored.  If
     308     optional arg 'onerror' is specified, it should be a function; it
     309     will be called with one argument, an OSError instance.  It can
     310     report the error to continue with the walk, or raise the exception
     311     to abort the walk.  Note that the filename is available as the
     312     filename attribute of the exception object.
     313 
     314     By default, os.walk does not follow symbolic links to subdirectories on
     315     systems that support them.  In order to get this functionality, set the
     316     optional argument 'followlinks' to true.
     317 
     318     Caution:  if you pass a relative pathname for top, don't change the
     319     current working directory between resumptions of walk.  walk never
     320     changes the current directory, and assumes that the client doesn't
     321     either.
     322 
     323     Example:
     324 
     325     import os
     326     from os.path import join, getsize
     327     for root, dirs, files in os.walk('python/Lib/email'):
     328         print(root, "consumes", end="")
     329         print(sum([getsize(join(root, name)) for name in files]), end="")
     330         print("bytes in", len(files), "non-directory files")
     331         if 'CVS' in dirs:
     332             dirs.remove('CVS')  # don't visit CVS directories
     333 
     334     """
     335     top = fspath(top)
     336     dirs = []
     337     nondirs = []
     338     walk_dirs = []
     339 
     340     # We may not have read permission for top, in which case we can't
     341     # get a list of the files the directory contains.  os.walk
     342     # always suppressed the exception then, rather than blow up for a
     343     # minor reason when (say) a thousand readable directories are still
     344     # left to visit.  That logic is copied here.
     345     try:
     346         # Note that scandir is global in this module due
     347         # to earlier import-*.
     348         scandir_it = scandir(top)
     349     except OSError as error:
     350         if onerror is not None:
     351             onerror(error)
     352         return
     353 
     354     with scandir_it:
     355         while True:
     356             try:
     357                 try:
     358                     entry = next(scandir_it)
     359                 except StopIteration:
     360                     break
     361             except OSError as error:
     362                 if onerror is not None:
     363                     onerror(error)
     364                 return
     365 
     366             try:
     367                 is_dir = entry.is_dir()
     368             except OSError:
     369                 # If is_dir() raises an OSError, consider that the entry is not
     370                 # a directory, same behaviour than os.path.isdir().
     371                 is_dir = False
     372 
     373             if is_dir:
     374                 dirs.append(entry.name)
     375             else:
     376                 nondirs.append(entry.name)
     377 
     378             if not topdown and is_dir:
     379                 # Bottom-up: recurse into sub-directory, but exclude symlinks to
     380                 # directories if followlinks is False
     381                 if followlinks:
     382                     walk_into = True
     383                 else:
     384                     try:
     385                         is_symlink = entry.is_symlink()
     386                     except OSError:
     387                         # If is_symlink() raises an OSError, consider that the
     388                         # entry is not a symbolic link, same behaviour than
     389                         # os.path.islink().
     390                         is_symlink = False
     391                     walk_into = not is_symlink
     392 
     393                 if walk_into:
     394                     walk_dirs.append(entry.path)
     395 
     396     # Yield before recursion if going top down
     397     if topdown:
     398         yield top, dirs, nondirs
     399 
     400         # Recurse into sub-directories
     401         islink, join = path.islink, path.join
     402         for dirname in dirs:
     403             new_path = join(top, dirname)
     404             # Issue #23605: os.path.islink() is used instead of caching
     405             # entry.is_symlink() result during the loop on os.scandir() because
     406             # the caller can replace the directory entry during the "yield"
     407             # above.
     408             if followlinks or not islink(new_path):
     409                 yield from walk(new_path, topdown, onerror, followlinks)
     410     else:
     411         # Recurse into sub-directories
     412         for new_path in walk_dirs:
     413             yield from walk(new_path, topdown, onerror, followlinks)
     414         # Yield after recursion if going bottom up
     415         yield top, dirs, nondirs
     416 
     417 __all__.append("walk")
     418 
     419 if {open, stat} <= supports_dir_fd and {listdir, stat} <= supports_fd:
     420 
     421     def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None):
     422         """Directory tree generator.
     423 
     424         This behaves exactly like walk(), except that it yields a 4-tuple
     425 
     426             dirpath, dirnames, filenames, dirfd
     427 
     428         `dirpath`, `dirnames` and `filenames` are identical to walk() output,
     429         and `dirfd` is a file descriptor referring to the directory `dirpath`.
     430 
     431         The advantage of fwalk() over walk() is that it's safe against symlink
     432         races (when follow_symlinks is False).
     433 
     434         If dir_fd is not None, it should be a file descriptor open to a directory,
     435           and top should be relative; top will then be relative to that directory.
     436           (dir_fd is always supported for fwalk.)
     437 
     438         Caution:
     439         Since fwalk() yields file descriptors, those are only valid until the
     440         next iteration step, so you should dup() them if you want to keep them
     441         for a longer period.
     442 
     443         Example:
     444 
     445         import os
     446         for root, dirs, files, rootfd in os.fwalk('python/Lib/email'):
     447             print(root, "consumes", end="")
     448             print(sum([os.stat(name, dir_fd=rootfd).st_size for name in files]),
     449                   end="")
     450             print("bytes in", len(files), "non-directory files")
     451             if 'CVS' in dirs:
     452                 dirs.remove('CVS')  # don't visit CVS directories
     453         """
     454         if not isinstance(top, int) or not hasattr(top, '__index__'):
     455             top = fspath(top)
     456         # Note: To guard against symlink races, we use the standard
     457         # lstat()/open()/fstat() trick.
     458         orig_st = stat(top, follow_symlinks=False, dir_fd=dir_fd)
     459         topfd = open(top, O_RDONLY, dir_fd=dir_fd)
     460         try:
     461             if (follow_symlinks or (st.S_ISDIR(orig_st.st_mode) and
     462                                     path.samestat(orig_st, stat(topfd)))):
     463                 yield from _fwalk(topfd, top, topdown, onerror, follow_symlinks)
     464         finally:
     465             close(topfd)
     466 
     467     def _fwalk(topfd, toppath, topdown, onerror, follow_symlinks):
     468         # Note: This uses O(depth of the directory tree) file descriptors: if
     469         # necessary, it can be adapted to only require O(1) FDs, see issue
     470         # #13734.
     471 
     472         names = listdir(topfd)
     473         dirs, nondirs = [], []
     474         for name in names:
     475             try:
     476                 # Here, we don't use AT_SYMLINK_NOFOLLOW to be consistent with
     477                 # walk() which reports symlinks to directories as directories.
     478                 # We do however check for symlinks before recursing into
     479                 # a subdirectory.
     480                 if st.S_ISDIR(stat(name, dir_fd=topfd).st_mode):
     481                     dirs.append(name)
     482                 else:
     483                     nondirs.append(name)
     484             except OSError:
     485                 try:
     486                     # Add dangling symlinks, ignore disappeared files
     487                     if st.S_ISLNK(stat(name, dir_fd=topfd, follow_symlinks=False)
     488                                 .st_mode):
     489                         nondirs.append(name)
     490                 except OSError:
     491                     continue
     492 
     493         if topdown:
     494             yield toppath, dirs, nondirs, topfd
     495 
     496         for name in dirs:
     497             try:
     498                 orig_st = stat(name, dir_fd=topfd, follow_symlinks=follow_symlinks)
     499                 dirfd = open(name, O_RDONLY, dir_fd=topfd)
     500             except OSError as err:
     501                 if onerror is not None:
     502                     onerror(err)
     503                 continue
     504             try:
     505                 if follow_symlinks or path.samestat(orig_st, stat(dirfd)):
     506                     dirpath = path.join(toppath, name)
     507                     yield from _fwalk(dirfd, dirpath, topdown, onerror, follow_symlinks)
     508             finally:
     509                 close(dirfd)
     510 
     511         if not topdown:
     512             yield toppath, dirs, nondirs, topfd
     513 
     514     __all__.append("fwalk")
     515 
     516 # Make sure os.environ exists, at least
     517 try:
     518     environ
     519 except NameError:
     520     environ = {}
     521 
     522 def execl(file, *args):
     523     """execl(file, *args)
     524 
     525     Execute the executable file with argument list args, replacing the
     526     current process. """
     527     execv(file, args)
     528 
     529 def execle(file, *args):
     530     """execle(file, *args, env)
     531 
     532     Execute the executable file with argument list args and
     533     environment env, replacing the current process. """
     534     env = args[-1]
     535     execve(file, args[:-1], env)
     536 
     537 def execlp(file, *args):
     538     """execlp(file, *args)
     539 
     540     Execute the executable file (which is searched for along $PATH)
     541     with argument list args, replacing the current process. """
     542     execvp(file, args)
     543 
     544 def execlpe(file, *args):
     545     """execlpe(file, *args, env)
     546 
     547     Execute the executable file (which is searched for along $PATH)
     548     with argument list args and environment env, replacing the current
     549     process. """
     550     env = args[-1]
     551     execvpe(file, args[:-1], env)
     552 
     553 def execvp(file, args):
     554     """execvp(file, args)
     555 
     556     Execute the executable file (which is searched for along $PATH)
     557     with argument list args, replacing the current process.
     558     args may be a list or tuple of strings. """
     559     _execvpe(file, args)
     560 
     561 def execvpe(file, args, env):
     562     """execvpe(file, args, env)
     563 
     564     Execute the executable file (which is searched for along $PATH)
     565     with argument list args and environment env , replacing the
     566     current process.
     567     args may be a list or tuple of strings. """
     568     _execvpe(file, args, env)
     569 
     570 __all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
     571 
     572 def _execvpe(file, args, env=None):
     573     if env is not None:
     574         exec_func = execve
     575         argrest = (args, env)
     576     else:
     577         exec_func = execv
     578         argrest = (args,)
     579         env = environ
     580 
     581     head, tail = path.split(file)
     582     if head:
     583         exec_func(file, *argrest)
     584         return
     585     last_exc = saved_exc = None
     586     saved_tb = None
     587     path_list = get_exec_path(env)
     588     if name != 'nt':
     589         file = fsencode(file)
     590         path_list = map(fsencode, path_list)
     591     for dir in path_list:
     592         fullname = path.join(dir, file)
     593         try:
     594             exec_func(fullname, *argrest)
     595         except OSError as e:
     596             last_exc = e
     597             tb = sys.exc_info()[2]
     598             if (e.errno != errno.ENOENT and e.errno != errno.ENOTDIR
     599                 and saved_exc is None):
     600                 saved_exc = e
     601                 saved_tb = tb
     602     if saved_exc:
     603         raise saved_exc.with_traceback(saved_tb)
     604     raise last_exc.with_traceback(tb)
     605 
     606 
     607 def get_exec_path(env=None):
     608     """Returns the sequence of directories that will be searched for the
     609     named executable (similar to a shell) when launching a process.
     610 
     611     *env* must be an environment variable dict or None.  If *env* is None,
     612     os.environ will be used.
     613     """
     614     # Use a local import instead of a global import to limit the number of
     615     # modules loaded at startup: the os module is always loaded at startup by
     616     # Python. It may also avoid a bootstrap issue.
     617     import warnings
     618 
     619     if env is None:
     620         env = environ
     621 
     622     # {b'PATH': ...}.get('PATH') and {'PATH': ...}.get(b'PATH') emit a
     623     # BytesWarning when using python -b or python -bb: ignore the warning
     624     with warnings.catch_warnings():
     625         warnings.simplefilter("ignore", BytesWarning)
     626 
     627         try:
     628             path_list = env.get('PATH')
     629         except TypeError:
     630             path_list = None
     631 
     632         if supports_bytes_environ:
     633             try:
     634                 path_listb = env[b'PATH']
     635             except (KeyError, TypeError):
     636                 pass
     637             else:
     638                 if path_list is not None:
     639                     raise ValueError(
     640                         "env cannot contain 'PATH' and b'PATH' keys")
     641                 path_list = path_listb
     642 
     643             if path_list is not None and isinstance(path_list, bytes):
     644                 path_list = fsdecode(path_list)
     645 
     646     if path_list is None:
     647         path_list = defpath
     648     return path_list.split(pathsep)
     649 
     650 
     651 # Change environ to automatically call putenv(), unsetenv if they exist.
     652 from _collections_abc import MutableMapping
     653 
     654 class _Environ(MutableMapping):
     655     def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv):
     656         self.encodekey = encodekey
     657         self.decodekey = decodekey
     658         self.encodevalue = encodevalue
     659         self.decodevalue = decodevalue
     660         self.putenv = putenv
     661         self.unsetenv = unsetenv
     662         self._data = data
     663 
     664     def __getitem__(self, key):
     665         try:
     666             value = self._data[self.encodekey(key)]
     667         except KeyError:
     668             # raise KeyError with the original key value
     669             raise KeyError(key) from None
     670         return self.decodevalue(value)
     671 
     672     def __setitem__(self, key, value):
     673         key = self.encodekey(key)
     674         value = self.encodevalue(value)
     675         self.putenv(key, value)
     676         self._data[key] = value
     677 
     678     def __delitem__(self, key):
     679         encodedkey = self.encodekey(key)
     680         self.unsetenv(encodedkey)
     681         try:
     682             del self._data[encodedkey]
     683         except KeyError:
     684             # raise KeyError with the original key value
     685             raise KeyError(key) from None
     686 
     687     def __iter__(self):
     688         # list() from dict object is an atomic operation
     689         keys = list(self._data)
     690         for key in keys:
     691             yield self.decodekey(key)
     692 
     693     def __len__(self):
     694         return len(self._data)
     695 
     696     def __repr__(self):
     697         return 'environ({{{}}})'.format(', '.join(
     698             ('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value))
     699             for key, value in self._data.items())))
     700 
     701     def copy(self):
     702         return dict(self)
     703 
     704     def setdefault(self, key, value):
     705         if key not in self:
     706             self[key] = value
     707         return self[key]
     708 
     709 try:
     710     _putenv = putenv
     711 except NameError:
     712     _putenv = lambda key, value: None
     713 else:
     714     if "putenv" not in __all__:
     715         __all__.append("putenv")
     716 
     717 try:
     718     _unsetenv = unsetenv
     719 except NameError:
     720     _unsetenv = lambda key: _putenv(key, "")
     721 else:
     722     if "unsetenv" not in __all__:
     723         __all__.append("unsetenv")
     724 
     725 def _createenviron():
     726     if name == 'nt':
     727         # Where Env Var Names Must Be UPPERCASE
     728         def check_str(value):
     729             if not isinstance(value, str):
     730                 raise TypeError("str expected, not %s" % type(value).__name__)
     731             return value
     732         encode = check_str
     733         decode = str
     734         def encodekey(key):
     735             return encode(key).upper()
     736         data = {}
     737         for key, value in environ.items():
     738             data[encodekey(key)] = value
     739     else:
     740         # Where Env Var Names Can Be Mixed Case
     741         encoding = sys.getfilesystemencoding()
     742         def encode(value):
     743             if not isinstance(value, str):
     744                 raise TypeError("str expected, not %s" % type(value).__name__)
     745             return value.encode(encoding, 'surrogateescape')
     746         def decode(value):
     747             return value.decode(encoding, 'surrogateescape')
     748         encodekey = encode
     749         data = environ
     750     return _Environ(data,
     751         encodekey, decode,
     752         encode, decode,
     753         _putenv, _unsetenv)
     754 
     755 # unicode environ
     756 environ = _createenviron()
     757 del _createenviron
     758 
     759 
     760 def getenv(key, default=None):
     761     """Get an environment variable, return None if it doesn't exist.
     762     The optional second argument can specify an alternate default.
     763     key, default and the result are str."""
     764     return environ.get(key, default)
     765 
     766 supports_bytes_environ = (name != 'nt')
     767 __all__.extend(("getenv", "supports_bytes_environ"))
     768 
     769 if supports_bytes_environ:
     770     def _check_bytes(value):
     771         if not isinstance(value, bytes):
     772             raise TypeError("bytes expected, not %s" % type(value).__name__)
     773         return value
     774 
     775     # bytes environ
     776     environb = _Environ(environ._data,
     777         _check_bytes, bytes,
     778         _check_bytes, bytes,
     779         _putenv, _unsetenv)
     780     del _check_bytes
     781 
     782     def getenvb(key, default=None):
     783         """Get an environment variable, return None if it doesn't exist.
     784         The optional second argument can specify an alternate default.
     785         key, default and the result are bytes."""
     786         return environb.get(key, default)
     787 
     788     __all__.extend(("environb", "getenvb"))
     789 
     790 def _fscodec():
     791     encoding = sys.getfilesystemencoding()
     792     errors = sys.getfilesystemencodeerrors()
     793 
     794     def fsencode(filename):
     795         """Encode filename (an os.PathLike, bytes, or str) to the filesystem
     796         encoding with 'surrogateescape' error handler, return bytes unchanged.
     797         On Windows, use 'strict' error handler if the file system encoding is
     798         'mbcs' (which is the default encoding).
     799         """
     800         filename = fspath(filename)  # Does type-checking of `filename`.
     801         if isinstance(filename, str):
     802             return filename.encode(encoding, errors)
     803         else:
     804             return filename
     805 
     806     def fsdecode(filename):
     807         """Decode filename (an os.PathLike, bytes, or str) from the filesystem
     808         encoding with 'surrogateescape' error handler, return str unchanged. On
     809         Windows, use 'strict' error handler if the file system encoding is
     810         'mbcs' (which is the default encoding).
     811         """
     812         filename = fspath(filename)  # Does type-checking of `filename`.
     813         if isinstance(filename, bytes):
     814             return filename.decode(encoding, errors)
     815         else:
     816             return filename
     817 
     818     return fsencode, fsdecode
     819 
     820 fsencode, fsdecode = _fscodec()
     821 del _fscodec
     822 
     823 # Supply spawn*() (probably only for Unix)
     824 if _exists("fork") and not _exists("spawnv") and _exists("execv"):
     825 
     826     P_WAIT = 0
     827     P_NOWAIT = P_NOWAITO = 1
     828 
     829     __all__.extend(["P_WAIT", "P_NOWAIT", "P_NOWAITO"])
     830 
     831     # XXX Should we support P_DETACH?  I suppose it could fork()**2
     832     # and close the std I/O streams.  Also, P_OVERLAY is the same
     833     # as execv*()?
     834 
     835     def _spawnvef(mode, file, args, env, func):
     836         # Internal helper; func is the exec*() function to use
     837         if not isinstance(args, (tuple, list)):
     838             raise TypeError('argv must be a tuple or a list')
     839         if not args or not args[0]:
     840             raise ValueError('argv first element cannot be empty')
     841         pid = fork()
     842         if not pid:
     843             # Child
     844             try:
     845                 if env is None:
     846                     func(file, args)
     847                 else:
     848                     func(file, args, env)
     849             except:
     850                 _exit(127)
     851         else:
     852             # Parent
     853             if mode == P_NOWAIT:
     854                 return pid # Caller is responsible for waiting!
     855             while 1:
     856                 wpid, sts = waitpid(pid, 0)
     857                 if WIFSTOPPED(sts):
     858                     continue
     859                 elif WIFSIGNALED(sts):
     860                     return -WTERMSIG(sts)
     861                 elif WIFEXITED(sts):
     862                     return WEXITSTATUS(sts)
     863                 else:
     864                     raise OSError("Not stopped, signaled or exited???")
     865 
     866     def spawnv(mode, file, args):
     867         """spawnv(mode, file, args) -> integer
     868 
     869 Execute file with arguments from args in a subprocess.
     870 If mode == P_NOWAIT return the pid of the process.
     871 If mode == P_WAIT return the process's exit code if it exits normally;
     872 otherwise return -SIG, where SIG is the signal that killed it. """
     873         return _spawnvef(mode, file, args, None, execv)
     874 
     875     def spawnve(mode, file, args, env):
     876         """spawnve(mode, file, args, env) -> integer
     877 
     878 Execute file with arguments from args in a subprocess with the
     879 specified environment.
     880 If mode == P_NOWAIT return the pid of the process.
     881 If mode == P_WAIT return the process's exit code if it exits normally;
     882 otherwise return -SIG, where SIG is the signal that killed it. """
     883         return _spawnvef(mode, file, args, env, execve)
     884 
     885     # Note: spawnvp[e] is't currently supported on Windows
     886 
     887     def spawnvp(mode, file, args):
     888         """spawnvp(mode, file, args) -> integer
     889 
     890 Execute file (which is looked for along $PATH) with arguments from
     891 args in a subprocess.
     892 If mode == P_NOWAIT return the pid of the process.
     893 If mode == P_WAIT return the process's exit code if it exits normally;
     894 otherwise return -SIG, where SIG is the signal that killed it. """
     895         return _spawnvef(mode, file, args, None, execvp)
     896 
     897     def spawnvpe(mode, file, args, env):
     898         """spawnvpe(mode, file, args, env) -> integer
     899 
     900 Execute file (which is looked for along $PATH) with arguments from
     901 args in a subprocess with the supplied environment.
     902 If mode == P_NOWAIT return the pid of the process.
     903 If mode == P_WAIT return the process's exit code if it exits normally;
     904 otherwise return -SIG, where SIG is the signal that killed it. """
     905         return _spawnvef(mode, file, args, env, execvpe)
     906 
     907 
     908     __all__.extend(["spawnv", "spawnve", "spawnvp", "spawnvpe"])
     909 
     910 
     911 if _exists("spawnv"):
     912     # These aren't supplied by the basic Windows code
     913     # but can be easily implemented in Python
     914 
     915     def spawnl(mode, file, *args):
     916         """spawnl(mode, file, *args) -> integer
     917 
     918 Execute file with arguments from args in a subprocess.
     919 If mode == P_NOWAIT return the pid of the process.
     920 If mode == P_WAIT return the process's exit code if it exits normally;
     921 otherwise return -SIG, where SIG is the signal that killed it. """
     922         return spawnv(mode, file, args)
     923 
     924     def spawnle(mode, file, *args):
     925         """spawnle(mode, file, *args, env) -> integer
     926 
     927 Execute file with arguments from args in a subprocess with the
     928 supplied environment.
     929 If mode == P_NOWAIT return the pid of the process.
     930 If mode == P_WAIT return the process's exit code if it exits normally;
     931 otherwise return -SIG, where SIG is the signal that killed it. """
     932         env = args[-1]
     933         return spawnve(mode, file, args[:-1], env)
     934 
     935 
     936     __all__.extend(["spawnl", "spawnle"])
     937 
     938 
     939 if _exists("spawnvp"):
     940     # At the moment, Windows doesn't implement spawnvp[e],
     941     # so it won't have spawnlp[e] either.
     942     def spawnlp(mode, file, *args):
     943         """spawnlp(mode, file, *args) -> integer
     944 
     945 Execute file (which is looked for along $PATH) with arguments from
     946 args in a subprocess with the supplied environment.
     947 If mode == P_NOWAIT return the pid of the process.
     948 If mode == P_WAIT return the process's exit code if it exits normally;
     949 otherwise return -SIG, where SIG is the signal that killed it. """
     950         return spawnvp(mode, file, args)
     951 
     952     def spawnlpe(mode, file, *args):
     953         """spawnlpe(mode, file, *args, env) -> integer
     954 
     955 Execute file (which is looked for along $PATH) with arguments from
     956 args in a subprocess with the supplied environment.
     957 If mode == P_NOWAIT return the pid of the process.
     958 If mode == P_WAIT return the process's exit code if it exits normally;
     959 otherwise return -SIG, where SIG is the signal that killed it. """
     960         env = args[-1]
     961         return spawnvpe(mode, file, args[:-1], env)
     962 
     963 
     964     __all__.extend(["spawnlp", "spawnlpe"])
     965 
     966 
     967 # Supply os.popen()
     968 def popen(cmd, mode="r", buffering=-1):
     969     if not isinstance(cmd, str):
     970         raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
     971     if mode not in ("r", "w"):
     972         raise ValueError("invalid mode %r" % mode)
     973     if buffering == 0 or buffering is None:
     974         raise ValueError("popen() does not support unbuffered streams")
     975     import subprocess, io
     976     if mode == "r":
     977         proc = subprocess.Popen(cmd,
     978                                 shell=True,
     979                                 stdout=subprocess.PIPE,
     980                                 bufsize=buffering)
     981         return _wrap_close(io.TextIOWrapper(proc.stdout), proc)
     982     else:
     983         proc = subprocess.Popen(cmd,
     984                                 shell=True,
     985                                 stdin=subprocess.PIPE,
     986                                 bufsize=buffering)
     987         return _wrap_close(io.TextIOWrapper(proc.stdin), proc)
     988 
     989 # Helper for popen() -- a proxy for a file whose close waits for the process
     990 class _wrap_close:
     991     def __init__(self, stream, proc):
     992         self._stream = stream
     993         self._proc = proc
     994     def close(self):
     995         self._stream.close()
     996         returncode = self._proc.wait()
     997         if returncode == 0:
     998             return None
     999         if name == 'nt':
    1000             return returncode
    1001         else:
    1002             return returncode << 8  # Shift left to match old behavior
    1003     def __enter__(self):
    1004         return self
    1005     def __exit__(self, *args):
    1006         self.close()
    1007     def __getattr__(self, name):
    1008         return getattr(self._stream, name)
    1009     def __iter__(self):
    1010         return iter(self._stream)
    1011 
    1012 # Supply os.fdopen()
    1013 def fdopen(fd, *args, **kwargs):
    1014     if not isinstance(fd, int):
    1015         raise TypeError("invalid fd type (%s, expected integer)" % type(fd))
    1016     import io
    1017     return io.open(fd, *args, **kwargs)
    1018 
    1019 
    1020 # For testing purposes, make sure the function is available when the C
    1021 # implementation exists.
    1022 def _fspath(path):
    1023     """Return the path representation of a path-like object.
    1024 
    1025     If str or bytes is passed in, it is returned unchanged. Otherwise the
    1026     os.PathLike interface is used to get the path representation. If the
    1027     path representation is not str or bytes, TypeError is raised. If the
    1028     provided path is not str, bytes, or os.PathLike, TypeError is raised.
    1029     """
    1030     if isinstance(path, (str, bytes)):
    1031         return path
    1032 
    1033     # Work from the object's type to match method resolution of other magic
    1034     # methods.
    1035     path_type = type(path)
    1036     try:
    1037         path_repr = path_type.__fspath__(path)
    1038     except AttributeError:
    1039         if hasattr(path_type, '__fspath__'):
    1040             raise
    1041         else:
    1042             raise TypeError("expected str, bytes or os.PathLike object, "
    1043                             "not " + path_type.__name__)
    1044     if isinstance(path_repr, (str, bytes)):
    1045         return path_repr
    1046     else:
    1047         raise TypeError("expected {}.__fspath__() to return str or bytes, "
    1048                         "not {}".format(path_type.__name__,
    1049                                         type(path_repr).__name__))
    1050 
    1051 # If there is no C implementation, make the pure Python version the
    1052 # implementation as transparently as possible.
    1053 if not _exists('fspath'):
    1054     fspath = _fspath
    1055     fspath.__name__ = "fspath"
    1056 
    1057 
    1058 class PathLike(abc.ABC):
    1059 
    1060     """Abstract base class for implementing the file system path protocol."""
    1061 
    1062     @abc.abstractmethod
    1063     def __fspath__(self):
    1064         """Return the file system path representation of the object."""
    1065         raise NotImplementedError
    1066 
    1067     @classmethod
    1068     def __subclasshook__(cls, subclass):
    1069         return hasattr(subclass, '__fspath__')
    python:os
    每天更新一点点,温习一点点点,进步一点点
  • 相关阅读:
    从尾到头打印链表(基于js)
    替换空格(基于js)
    二维数组的查找(基于js)
    关于document对象
    js之DOM操作总结
    将博客搬至CSDN
    关于js中的数组
    干货集中营
    vim编辑器学习记录
    python3 多线程爆破ftp、mysql、ssh
  • 原文地址:https://www.cnblogs.com/lmgsanm/p/8349451.html
Copyright © 2011-2022 走看看