os

os模块提供便捷的与操作系统交互的方法。

1, os.name 

 导入的操作系统相关模块的名称,现在已经注册的有:'posix',‘nt’,'java'

2, os.uname() 

posix.uname_result(sysname='Linux', nodename='gate02', release='3.10.0-957.5.1.el7.x86_64', version='#1 SMP Fri Feb 1 14:54:57 UTC 2019', machine='x86_64')

用于显示系统相关信息,与sys.platform相似

3, os.ctermid() 

仅unix可用,返回进程控制端对应的文件名

'/dev/tty'

4, os.environ  os.environb 

显示所有环境变量,也可以指定

>>> os.environ['VIVADO_HOME']
'/home/eda/xilinx/Vivado/2017.4'

5, os.chdir(path) 切换路径

6, os.getcwd() 查看当前路径

7, os.fchdir(fd) 通过文件描述符fd切换路径

8, os.getenv(key,defualt=none)  得到环境变量值

>>> os.getenv('VCS_HOME',)
'/home/eda/synopsys/vcs/M-2017.03-SP2-10'

9, os.get_exec_path(env=None)  得到可执行文件的路径

10, os.getegid()  return the effective group id of the current process.--set id--only unix

11, os.geteuid()  return the effective user id of the current process. --only unix

12, os.getgid()  return the real group id of the current process. --only unix

13, os.getgrouplist(user,group)  Return list of group ids that user belongs to. --only unix

>>> os.getgrouplist('yuzhimin',1)
[1, 9002, 9001, 9010, 9003]
>>> os.getgrouplist('yuzhimin',9002)
[9002, 9001, 9010, 9003]

与linux下: id user 功能类似

14, os.getgroups()  Return list of supplemental group ids associated with the current process. --only unix

>>> os.getgroups()
[9001, 9002, 9003, 9010, 9016, 100251]

与linux下groups功能类似

15, os.getlogin()  Return the name of the user logged in on the controlling terminal of the process

16, os.getpgid(pid)  Return the process group id of the process with process id pid. If pid is 0, the process group id of the current process is returned --only unix

17, os.getpgrp()  Return the id of the current process group.--only unix

18, os.getpid()  Return the current process id

19, os.getppid()  Return the parent’s process id

20, os.listdir(path)  Return a list containing the names of the entries in the directory given by path

21, os.mkdir(path,mode=0o777,*,dir_fd=None)  Create a directory named path with numeric mode mode

22, os.remove(path,*,dir_fd=None)  

23, os.removedirs(path)  

   1 r"""OS routines for NT or Posix depending on what system we're on.
   2 
   3 
   4 
   5 This exports:
   6 
   7   - all functions from posix or nt, e.g. unlink, stat, etc.
   8 
   9   - os.path is either posixpath or ntpath
  10 
  11   - os.name is either 'posix' or 'nt'
  12 
  13   - os.curdir is a string representing the current directory (always '.')
  14 
  15   - os.pardir is a string representing the parent directory (always '..')
  16 
  17   - os.sep is the (or a most common) pathname separator ('/' or '\')
  18 
  19   - os.extsep is the extension separator (always '.')
  20 
  21   - os.altsep is the alternate pathname separator (None or '/')
  22 
  23   - os.pathsep is the component separator used in $PATH etc
  24 
  25   - os.linesep is the line separator in text files ('
' or '
' or '
')
  26 
  27   - os.defpath is the default search path for executables
  28 
  29   - os.devnull is the file path of the null device ('/dev/null', etc.)
  30 
  31 
  32 
  33 Programs that import and use 'os' stand a better chance of being
  34 
  35 portable between different platforms.  Of course, they must then
  36 
  37 only use functions that are defined by all platforms (e.g., unlink
  38 
  39 and opendir), and leave all pathname manipulation to os.path
  40 
  41 (e.g., split and join).
  42 
  43 """
  44 
  45 
  46 
  47 #'
  48 
  49 import abc
  50 
  51 import sys
  52 
  53 import stat as st
  54 
  55 
  56 
  57 from _collections_abc import _check_methods
  58 
  59 
  60 
  61 _names = sys.builtin_module_names
  62 
  63 
  64 
  65 # Note:  more names are added to __all__ later.
  66 
  67 __all__ = ["altsep", "curdir", "pardir", "sep", "pathsep", "linesep",
  68 
  69            "defpath", "name", "path", "devnull", "SEEK_SET", "SEEK_CUR",
  70 
  71            "SEEK_END", "fsencode", "fsdecode", "get_exec_path", "fdopen",
  72 
  73            "popen", "extsep"]
  74 
  75 
  76 
  77 def _exists(name):
  78 
  79     return name in globals()
  80 
  81 
  82 
  83 def _get_exports_list(module):
  84 
  85     try:
  86 
  87         return list(module.__all__)
  88 
  89     except AttributeError:
  90 
  91         return [n for n in dir(module) if n[0] != '_']
  92 
  93 
  94 
  95 # Any new dependencies of the os module and/or changes in path separator
  96 
  97 # requires updating importlib as well.
  98 
  99 if 'posix' in _names:
 100 
 101     name = 'posix'
 102 
 103     linesep = '
'
 104 
 105     from posix import *
 106 
 107     try:
 108 
 109         from posix import _exit
 110 
 111         __all__.append('_exit')
 112 
 113     except ImportError:
 114 
 115         pass
 116 
 117     import posixpath as path
 118 
 119 
 120 
 121     try:
 122 
 123         from posix import _have_functions
 124 
 125     except ImportError:
 126 
 127         pass
 128 
 129 
 130 
 131     import posix
 132 
 133     __all__.extend(_get_exports_list(posix))
 134 
 135     del posix
 136 
 137 
 138 
 139 elif 'nt' in _names:
 140 
 141     name = 'nt'
 142 
 143     linesep = '
'
 144 
 145     from nt import *
 146 
 147     try:
 148 
 149         from nt import _exit
 150 
 151         __all__.append('_exit')
 152 
 153     except ImportError:
 154 
 155         pass
 156 
 157     import ntpath as path
 158 
 159 
 160 
 161     import nt
 162 
 163     __all__.extend(_get_exports_list(nt))
 164 
 165     del nt
 166 
 167 
 168 
 169     try:
 170 
 171         from nt import _have_functions
 172 
 173     except ImportError:
 174 
 175         pass
 176 
 177 
 178 
 179 else:
 180 
 181     raise ImportError('no os specific module found')
 182 
 183 
 184 
 185 sys.modules['os.path'] = path
 186 
 187 from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep,
 188 
 189     devnull)
 190 
 191 
 192 
 193 del _names
 194 
 195 
 196 
 197 
 198 
 199 if _exists("_have_functions"):
 200 
 201     _globals = globals()
 202 
 203     def _add(str, fn):
 204 
 205         if (fn in _globals) and (str in _have_functions):
 206 
 207             _set.add(_globals[fn])
 208 
 209 
 210 
 211     _set = set()
 212 
 213     _add("HAVE_FACCESSAT",  "access")
 214 
 215     _add("HAVE_FCHMODAT",   "chmod")
 216 
 217     _add("HAVE_FCHOWNAT",   "chown")
 218 
 219     _add("HAVE_FSTATAT",    "stat")
 220 
 221     _add("HAVE_FUTIMESAT",  "utime")
 222 
 223     _add("HAVE_LINKAT",     "link")
 224 
 225     _add("HAVE_MKDIRAT",    "mkdir")
 226 
 227     _add("HAVE_MKFIFOAT",   "mkfifo")
 228 
 229     _add("HAVE_MKNODAT",    "mknod")
 230 
 231     _add("HAVE_OPENAT",     "open")
 232 
 233     _add("HAVE_READLINKAT", "readlink")
 234 
 235     _add("HAVE_RENAMEAT",   "rename")
 236 
 237     _add("HAVE_SYMLINKAT",  "symlink")
 238 
 239     _add("HAVE_UNLINKAT",   "unlink")
 240 
 241     _add("HAVE_UNLINKAT",   "rmdir")
 242 
 243     _add("HAVE_UTIMENSAT",  "utime")
 244 
 245     supports_dir_fd = _set
 246 
 247 
 248 
 249     _set = set()
 250 
 251     _add("HAVE_FACCESSAT",  "access")
 252 
 253     supports_effective_ids = _set
 254 
 255 
 256 
 257     _set = set()
 258 
 259     _add("HAVE_FCHDIR",     "chdir")
 260 
 261     _add("HAVE_FCHMOD",     "chmod")
 262 
 263     _add("HAVE_FCHOWN",     "chown")
 264 
 265     _add("HAVE_FDOPENDIR",  "listdir")
 266 
 267     _add("HAVE_FDOPENDIR",  "scandir")
 268 
 269     _add("HAVE_FEXECVE",    "execve")
 270 
 271     _set.add(stat) # fstat always works
 272 
 273     _add("HAVE_FTRUNCATE",  "truncate")
 274 
 275     _add("HAVE_FUTIMENS",   "utime")
 276 
 277     _add("HAVE_FUTIMES",    "utime")
 278 
 279     _add("HAVE_FPATHCONF",  "pathconf")
 280 
 281     if _exists("statvfs") and _exists("fstatvfs"): # mac os x10.3
 282 
 283         _add("HAVE_FSTATVFS", "statvfs")
 284 
 285     supports_fd = _set
 286 
 287 
 288 
 289     _set = set()
 290 
 291     _add("HAVE_FACCESSAT",  "access")
 292 
 293     # Some platforms don't support lchmod().  Often the function exists
 294 
 295     # anyway, as a stub that always returns ENOSUP or perhaps EOPNOTSUPP.
 296 
 297     # (No, I don't know why that's a good design.)  ./configure will detect
 298 
 299     # this and reject it--so HAVE_LCHMOD still won't be defined on such
 300 
 301     # platforms.  This is Very Helpful.
 302 
 303     #
 304 
 305     # However, sometimes platforms without a working lchmod() *do* have
 306 
 307     # fchmodat().  (Examples: Linux kernel 3.2 with glibc 2.15,
 308 
 309     # OpenIndiana 3.x.)  And fchmodat() has a flag that theoretically makes
 310 
 311     # it behave like lchmod().  So in theory it would be a suitable
 312 
 313     # replacement for lchmod().  But when lchmod() doesn't work, fchmodat()'s
 314 
 315     # flag doesn't work *either*.  Sadly ./configure isn't sophisticated
 316 
 317     # enough to detect this condition--it only determines whether or not
 318 
 319     # fchmodat() minimally works.
 320 
 321     #
 322 
 323     # Therefore we simply ignore fchmodat() when deciding whether or not
 324 
 325     # os.chmod supports follow_symlinks.  Just checking lchmod() is
 326 
 327     # sufficient.  After all--if you have a working fchmodat(), your
 328 
 329     # lchmod() almost certainly works too.
 330 
 331     #
 332 
 333     # _add("HAVE_FCHMODAT",   "chmod")
 334 
 335     _add("HAVE_FCHOWNAT",   "chown")
 336 
 337     _add("HAVE_FSTATAT",    "stat")
 338 
 339     _add("HAVE_LCHFLAGS",   "chflags")
 340 
 341     _add("HAVE_LCHMOD",     "chmod")
 342 
 343     if _exists("lchown"): # mac os x10.3
 344 
 345         _add("HAVE_LCHOWN", "chown")
 346 
 347     _add("HAVE_LINKAT",     "link")
 348 
 349     _add("HAVE_LUTIMES",    "utime")
 350 
 351     _add("HAVE_LSTAT",      "stat")
 352 
 353     _add("HAVE_FSTATAT",    "stat")
 354 
 355     _add("HAVE_UTIMENSAT",  "utime")
 356 
 357     _add("MS_WINDOWS",      "stat")
 358 
 359     supports_follow_symlinks = _set
 360 
 361 
 362 
 363     del _set
 364 
 365     del _have_functions
 366 
 367     del _globals
 368 
 369     del _add
 370 
 371 
 372 
 373 
 374 
 375 # Python uses fixed values for the SEEK_ constants; they are mapped
 376 
 377 # to native constants if necessary in posixmodule.c
 378 
 379 # Other possible SEEK values are directly imported from posixmodule.c
 380 
 381 SEEK_SET = 0
 382 
 383 SEEK_CUR = 1
 384 
 385 SEEK_END = 2
 386 
 387 
 388 
 389 # Super directory utilities.
 390 
 391 # (Inspired by Eric Raymond; the doc strings are mostly his)
 392 
 393 
 394 
 395 def makedirs(name, mode=0o777, exist_ok=False):
 396 
 397     """makedirs(name [, mode=0o777][, exist_ok=False])
 398 
 399 
 400 
 401     Super-mkdir; create a leaf directory and all intermediate ones.  Works like
 402 
 403     mkdir, except that any intermediate path segment (not just the rightmost)
 404 
 405     will be created if it does not exist. If the target directory already
 406 
 407     exists, raise an OSError if exist_ok is False. Otherwise no exception is
 408 
 409     raised.  This is recursive.
 410 
 411 
 412 
 413     """
 414 
 415     head, tail = path.split(name)
 416 
 417     if not tail:
 418 
 419         head, tail = path.split(head)
 420 
 421     if head and tail and not path.exists(head):
 422 
 423         try:
 424 
 425             makedirs(head, exist_ok=exist_ok)
 426 
 427         except FileExistsError:
 428 
 429             # Defeats race condition when another thread created the path
 430 
 431             pass
 432 
 433         cdir = curdir
 434 
 435         if isinstance(tail, bytes):
 436 
 437             cdir = bytes(curdir, 'ASCII')
 438 
 439         if tail == cdir:           # xxx/newdir/. exists if xxx/newdir exists
 440 
 441             return
 442 
 443     try:
 444 
 445         mkdir(name, mode)
 446 
 447     except OSError:
 448 
 449         # Cannot rely on checking for EEXIST, since the operating system
 450 
 451         # could give priority to other errors like EACCES or EROFS
 452 
 453         if not exist_ok or not path.isdir(name):
 454 
 455             raise
 456 
 457 
 458 
 459 def removedirs(name):
 460 
 461     """removedirs(name)
 462 
 463 
 464 
 465     Super-rmdir; remove a leaf directory and all empty intermediate
 466 
 467     ones.  Works like rmdir except that, if the leaf directory is
 468 
 469     successfully removed, directories corresponding to rightmost path
 470 
 471     segments will be pruned away until either the whole path is
 472 
 473     consumed or an error occurs.  Errors during this latter phase are
 474 
 475     ignored -- they generally mean that a directory was not empty.
 476 
 477 
 478 
 479     """
 480 
 481     rmdir(name)
 482 
 483     head, tail = path.split(name)
 484 
 485     if not tail:
 486 
 487         head, tail = path.split(head)
 488 
 489     while head and tail:
 490 
 491         try:
 492 
 493             rmdir(head)
 494 
 495         except OSError:
 496 
 497             break
 498 
 499         head, tail = path.split(head)
 500 
 501 
 502 
 503 def renames(old, new):
 504 
 505     """renames(old, new)
 506 
 507 
 508 
 509     Super-rename; create directories as necessary and delete any left
 510 
 511     empty.  Works like rename, except creation of any intermediate
 512 
 513     directories needed to make the new pathname good is attempted
 514 
 515     first.  After the rename, directories corresponding to rightmost
 516 
 517     path segments of the old name will be pruned until either the
 518 
 519     whole path is consumed or a nonempty directory is found.
 520 
 521 
 522 
 523     Note: this function can fail with the new directory structure made
 524 
 525     if you lack permissions needed to unlink the leaf directory or
 526 
 527     file.
 528 
 529 
 530 
 531     """
 532 
 533     head, tail = path.split(new)
 534 
 535     if head and tail and not path.exists(head):
 536 
 537         makedirs(head)
 538 
 539     rename(old, new)
 540 
 541     head, tail = path.split(old)
 542 
 543     if head and tail:
 544 
 545         try:
 546 
 547             removedirs(head)
 548 
 549         except OSError:
 550 
 551             pass
 552 
 553 
 554 
 555 __all__.extend(["makedirs", "removedirs", "renames"])
 556 
 557 
 558 
 559 def walk(top, topdown=True, onerror=None, followlinks=False):
 560 
 561     """Directory tree generator.
 562 
 563 
 564 
 565     For each directory in the directory tree rooted at top (including top
 566 
 567     itself, but excluding '.' and '..'), yields a 3-tuple
 568 
 569 
 570 
 571         dirpath, dirnames, filenames
 572 
 573 
 574 
 575     dirpath is a string, the path to the directory.  dirnames is a list of
 576 
 577     the names of the subdirectories in dirpath (excluding '.' and '..').
 578 
 579     filenames is a list of the names of the non-directory files in dirpath.
 580 
 581     Note that the names in the lists are just names, with no path components.
 582 
 583     To get a full path (which begins with top) to a file or directory in
 584 
 585     dirpath, do os.path.join(dirpath, name).
 586 
 587 
 588 
 589     If optional arg 'topdown' is true or not specified, the triple for a
 590 
 591     directory is generated before the triples for any of its subdirectories
 592 
 593     (directories are generated top down).  If topdown is false, the triple
 594 
 595     for a directory is generated after the triples for all of its
 596 
 597     subdirectories (directories are generated bottom up).
 598 
 599 
 600 
 601     When topdown is true, the caller can modify the dirnames list in-place
 602 
 603     (e.g., via del or slice assignment), and walk will only recurse into the
 604 
 605     subdirectories whose names remain in dirnames; this can be used to prune the
 606 
 607     search, or to impose a specific order of visiting.  Modifying dirnames when
 608 
 609     topdown is false has no effect on the behavior of os.walk(), since the
 610 
 611     directories in dirnames have already been generated by the time dirnames
 612 
 613     itself is generated. No matter the value of topdown, the list of
 614 
 615     subdirectories is retrieved before the tuples for the directory and its
 616 
 617     subdirectories are generated.
 618 
 619 
 620 
 621     By default errors from the os.scandir() call are ignored.  If
 622 
 623     optional arg 'onerror' is specified, it should be a function; it
 624 
 625     will be called with one argument, an OSError instance.  It can
 626 
 627     report the error to continue with the walk, or raise the exception
 628 
 629     to abort the walk.  Note that the filename is available as the
 630 
 631     filename attribute of the exception object.
 632 
 633 
 634 
 635     By default, os.walk does not follow symbolic links to subdirectories on
 636 
 637     systems that support them.  In order to get this functionality, set the
 638 
 639     optional argument 'followlinks' to true.
 640 
 641 
 642 
 643     Caution:  if you pass a relative pathname for top, don't change the
 644 
 645     current working directory between resumptions of walk.  walk never
 646 
 647     changes the current directory, and assumes that the client doesn't
 648 
 649     either.
 650 
 651 
 652 
 653     Example:
 654 
 655 
 656 
 657     import os
 658 
 659     from os.path import join, getsize
 660 
 661     for root, dirs, files in os.walk('python/Lib/email'):
 662 
 663         print(root, "consumes", end="")
 664 
 665         print(sum([getsize(join(root, name)) for name in files]), end="")
 666 
 667         print("bytes in", len(files), "non-directory files")
 668 
 669         if 'CVS' in dirs:
 670 
 671             dirs.remove('CVS')  # don't visit CVS directories
 672 
 673 
 674 
 675     """
 676 
 677     top = fspath(top)
 678 
 679     dirs = []
 680 
 681     nondirs = []
 682 
 683     walk_dirs = []
 684 
 685 
 686 
 687     # We may not have read permission for top, in which case we can't
 688 
 689     # get a list of the files the directory contains.  os.walk
 690 
 691     # always suppressed the exception then, rather than blow up for a
 692 
 693     # minor reason when (say) a thousand readable directories are still
 694 
 695     # left to visit.  That logic is copied here.
 696 
 697     try:
 698 
 699         # Note that scandir is global in this module due
 700 
 701         # to earlier import-*.
 702 
 703         scandir_it = scandir(top)
 704 
 705     except OSError as error:
 706 
 707         if onerror is not None:
 708 
 709             onerror(error)
 710 
 711         return
 712 
 713 
 714 
 715     with scandir_it:
 716 
 717         while True:
 718 
 719             try:
 720 
 721                 try:
 722 
 723                     entry = next(scandir_it)
 724 
 725                 except StopIteration:
 726 
 727                     break
 728 
 729             except OSError as error:
 730 
 731                 if onerror is not None:
 732 
 733                     onerror(error)
 734 
 735                 return
 736 
 737 
 738 
 739             try:
 740 
 741                 is_dir = entry.is_dir()
 742 
 743             except OSError:
 744 
 745                 # If is_dir() raises an OSError, consider that the entry is not
 746 
 747                 # a directory, same behaviour than os.path.isdir().
 748 
 749                 is_dir = False
 750 
 751 
 752 
 753             if is_dir:
 754 
 755                 dirs.append(entry.name)
 756 
 757             else:
 758 
 759                 nondirs.append(entry.name)
 760 
 761 
 762 
 763             if not topdown and is_dir:
 764 
 765                 # Bottom-up: recurse into sub-directory, but exclude symlinks to
 766 
 767                 # directories if followlinks is False
 768 
 769                 if followlinks:
 770 
 771                     walk_into = True
 772 
 773                 else:
 774 
 775                     try:
 776 
 777                         is_symlink = entry.is_symlink()
 778 
 779                     except OSError:
 780 
 781                         # If is_symlink() raises an OSError, consider that the
 782 
 783                         # entry is not a symbolic link, same behaviour than
 784 
 785                         # os.path.islink().
 786 
 787                         is_symlink = False
 788 
 789                     walk_into = not is_symlink
 790 
 791 
 792 
 793                 if walk_into:
 794 
 795                     walk_dirs.append(entry.path)
 796 
 797 
 798 
 799     # Yield before recursion if going top down
 800 
 801     if topdown:
 802 
 803         yield top, dirs, nondirs
 804 
 805 
 806 
 807         # Recurse into sub-directories
 808 
 809         islink, join = path.islink, path.join
 810 
 811         for dirname in dirs:
 812 
 813             new_path = join(top, dirname)
 814 
 815             # Issue #23605: os.path.islink() is used instead of caching
 816 
 817             # entry.is_symlink() result during the loop on os.scandir() because
 818 
 819             # the caller can replace the directory entry during the "yield"
 820 
 821             # above.
 822 
 823             if followlinks or not islink(new_path):
 824 
 825                 yield from walk(new_path, topdown, onerror, followlinks)
 826 
 827     else:
 828 
 829         # Recurse into sub-directories
 830 
 831         for new_path in walk_dirs:
 832 
 833             yield from walk(new_path, topdown, onerror, followlinks)
 834 
 835         # Yield after recursion if going bottom up
 836 
 837         yield top, dirs, nondirs
 838 
 839 
 840 
 841 __all__.append("walk")
 842 
 843 
 844 
 845 if {open, stat} <= supports_dir_fd and {scandir, stat} <= supports_fd:
 846 
 847 
 848 
 849     def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=None):
 850 
 851         """Directory tree generator.
 852 
 853 
 854 
 855         This behaves exactly like walk(), except that it yields a 4-tuple
 856 
 857 
 858 
 859             dirpath, dirnames, filenames, dirfd
 860 
 861 
 862 
 863         `dirpath`, `dirnames` and `filenames` are identical to walk() output,
 864 
 865         and `dirfd` is a file descriptor referring to the directory `dirpath`.
 866 
 867 
 868 
 869         The advantage of fwalk() over walk() is that it's safe against symlink
 870 
 871         races (when follow_symlinks is False).
 872 
 873 
 874 
 875         If dir_fd is not None, it should be a file descriptor open to a directory,
 876 
 877           and top should be relative; top will then be relative to that directory.
 878 
 879           (dir_fd is always supported for fwalk.)
 880 
 881 
 882 
 883         Caution:
 884 
 885         Since fwalk() yields file descriptors, those are only valid until the
 886 
 887         next iteration step, so you should dup() them if you want to keep them
 888 
 889         for a longer period.
 890 
 891 
 892 
 893         Example:
 894 
 895 
 896 
 897         import os
 898 
 899         for root, dirs, files, rootfd in os.fwalk('python/Lib/email'):
 900 
 901             print(root, "consumes", end="")
 902 
 903             print(sum([os.stat(name, dir_fd=rootfd).st_size for name in files]),
 904 
 905                   end="")
 906 
 907             print("bytes in", len(files), "non-directory files")
 908 
 909             if 'CVS' in dirs:
 910 
 911                 dirs.remove('CVS')  # don't visit CVS directories
 912 
 913         """
 914 
 915         if not isinstance(top, int) or not hasattr(top, '__index__'):
 916 
 917             top = fspath(top)
 918 
 919         # Note: To guard against symlink races, we use the standard
 920 
 921         # lstat()/open()/fstat() trick.
 922 
 923         if not follow_symlinks:
 924 
 925             orig_st = stat(top, follow_symlinks=False, dir_fd=dir_fd)
 926 
 927         topfd = open(top, O_RDONLY, dir_fd=dir_fd)
 928 
 929         try:
 930 
 931             if (follow_symlinks or (st.S_ISDIR(orig_st.st_mode) and
 932 
 933                                     path.samestat(orig_st, stat(topfd)))):
 934 
 935                 yield from _fwalk(topfd, top, isinstance(top, bytes),
 936 
 937                                   topdown, onerror, follow_symlinks)
 938 
 939         finally:
 940 
 941             close(topfd)
 942 
 943 
 944 
 945     def _fwalk(topfd, toppath, isbytes, topdown, onerror, follow_symlinks):
 946 
 947         # Note: This uses O(depth of the directory tree) file descriptors: if
 948 
 949         # necessary, it can be adapted to only require O(1) FDs, see issue
 950 
 951         # #13734.
 952 
 953 
 954 
 955         scandir_it = scandir(topfd)
 956 
 957         dirs = []
 958 
 959         nondirs = []
 960 
 961         entries = None if topdown or follow_symlinks else []
 962 
 963         for entry in scandir_it:
 964 
 965             name = entry.name
 966 
 967             if isbytes:
 968 
 969                 name = fsencode(name)
 970 
 971             try:
 972 
 973                 if entry.is_dir():
 974 
 975                     dirs.append(name)
 976 
 977                     if entries is not None:
 978 
 979                         entries.append(entry)
 980 
 981                 else:
 982 
 983                     nondirs.append(name)
 984 
 985             except OSError:
 986 
 987                 try:
 988 
 989                     # Add dangling symlinks, ignore disappeared files
 990 
 991                     if entry.is_symlink():
 992 
 993                         nondirs.append(name)
 994 
 995                 except OSError:
 996 
 997                     pass
 998 
 999 
1000 
1001         if topdown:
1002 
1003             yield toppath, dirs, nondirs, topfd
1004 
1005 
1006 
1007         for name in dirs if entries is None else zip(dirs, entries):
1008 
1009             try:
1010 
1011                 if not follow_symlinks:
1012 
1013                     if topdown:
1014 
1015                         orig_st = stat(name, dir_fd=topfd, follow_symlinks=False)
1016 
1017                     else:
1018 
1019                         assert entries is not None
1020 
1021                         name, entry = name
1022 
1023                         orig_st = entry.stat(follow_symlinks=False)
1024 
1025                 dirfd = open(name, O_RDONLY, dir_fd=topfd)
1026 
1027             except OSError as err:
1028 
1029                 if onerror is not None:
1030 
1031                     onerror(err)
1032 
1033                 continue
1034 
1035             try:
1036 
1037                 if follow_symlinks or path.samestat(orig_st, stat(dirfd)):
1038 
1039                     dirpath = path.join(toppath, name)
1040 
1041                     yield from _fwalk(dirfd, dirpath, isbytes,
1042 
1043                                       topdown, onerror, follow_symlinks)
1044 
1045             finally:
1046 
1047                 close(dirfd)
1048 
1049 
1050 
1051         if not topdown:
1052 
1053             yield toppath, dirs, nondirs, topfd
1054 
1055 
1056 
1057     __all__.append("fwalk")
1058 
1059 
1060 
1061 # Make sure os.environ exists, at least
1062 
1063 try:
1064 
1065     environ
1066 
1067 except NameError:
1068 
1069     environ = {}
1070 
1071 
1072 
1073 def execl(file, *args):
1074 
1075     """execl(file, *args)
1076 
1077 
1078 
1079     Execute the executable file with argument list args, replacing the
1080 
1081     current process. """
1082 
1083     execv(file, args)
1084 
1085 
1086 
1087 def execle(file, *args):
1088 
1089     """execle(file, *args, env)
1090 
1091 
1092 
1093     Execute the executable file with argument list args and
1094 
1095     environment env, replacing the current process. """
1096 
1097     env = args[-1]
1098 
1099     execve(file, args[:-1], env)
1100 
1101 
1102 
1103 def execlp(file, *args):
1104 
1105     """execlp(file, *args)
1106 
1107 
1108 
1109     Execute the executable file (which is searched for along $PATH)
1110 
1111     with argument list args, replacing the current process. """
1112 
1113     execvp(file, args)
1114 
1115 
1116 
1117 def execlpe(file, *args):
1118 
1119     """execlpe(file, *args, env)
1120 
1121 
1122 
1123     Execute the executable file (which is searched for along $PATH)
1124 
1125     with argument list args and environment env, replacing the current
1126 
1127     process. """
1128 
1129     env = args[-1]
1130 
1131     execvpe(file, args[:-1], env)
1132 
1133 
1134 
1135 def execvp(file, args):
1136 
1137     """execvp(file, args)
1138 
1139 
1140 
1141     Execute the executable file (which is searched for along $PATH)
1142 
1143     with argument list args, replacing the current process.
1144 
1145     args may be a list or tuple of strings. """
1146 
1147     _execvpe(file, args)
1148 
1149 
1150 
1151 def execvpe(file, args, env):
1152 
1153     """execvpe(file, args, env)
1154 
1155 
1156 
1157     Execute the executable file (which is searched for along $PATH)
1158 
1159     with argument list args and environment env, replacing the
1160 
1161     current process.
1162 
1163     args may be a list or tuple of strings. """
1164 
1165     _execvpe(file, args, env)
1166 
1167 
1168 
1169 __all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
1170 
1171 
1172 
1173 def _execvpe(file, args, env=None):
1174 
1175     if env is not None:
1176 
1177         exec_func = execve
1178 
1179         argrest = (args, env)
1180 
1181     else:
1182 
1183         exec_func = execv
1184 
1185         argrest = (args,)
1186 
1187         env = environ
1188 
1189 
1190 
1191     if path.dirname(file):
1192 
1193         exec_func(file, *argrest)
1194 
1195         return
1196 
1197     saved_exc = None
1198 
1199     path_list = get_exec_path(env)
1200 
1201     if name != 'nt':
1202 
1203         file = fsencode(file)
1204 
1205         path_list = map(fsencode, path_list)
1206 
1207     for dir in path_list:
1208 
1209         fullname = path.join(dir, file)
1210 
1211         try:
1212 
1213             exec_func(fullname, *argrest)
1214 
1215         except (FileNotFoundError, NotADirectoryError) as e:
1216 
1217             last_exc = e
1218 
1219         except OSError as e:
1220 
1221             last_exc = e
1222 
1223             if saved_exc is None:
1224 
1225                 saved_exc = e
1226 
1227     if saved_exc is not None:
1228 
1229         raise saved_exc
1230 
1231     raise last_exc
1232 
1233 
1234 
1235 
1236 
1237 def get_exec_path(env=None):
1238 
1239     """Returns the sequence of directories that will be searched for the
1240 
1241     named executable (similar to a shell) when launching a process.
1242 
1243 
1244 
1245     *env* must be an environment variable dict or None.  If *env* is None,
1246 
1247     os.environ will be used.
1248 
1249     """
1250 
1251     # Use a local import instead of a global import to limit the number of
1252 
1253     # modules loaded at startup: the os module is always loaded at startup by
1254 
1255     # Python. It may also avoid a bootstrap issue.
1256 
1257     import warnings
1258 
1259 
1260 
1261     if env is None:
1262 
1263         env = environ
1264 
1265 
1266 
1267     # {b'PATH': ...}.get('PATH') and {'PATH': ...}.get(b'PATH') emit a
1268 
1269     # BytesWarning when using python -b or python -bb: ignore the warning
1270 
1271     with warnings.catch_warnings():
1272 
1273         warnings.simplefilter("ignore", BytesWarning)
1274 
1275 
1276 
1277         try:
1278 
1279             path_list = env.get('PATH')
1280 
1281         except TypeError:
1282 
1283             path_list = None
1284 
1285 
1286 
1287         if supports_bytes_environ:
1288 
1289             try:
1290 
1291                 path_listb = env[b'PATH']
1292 
1293             except (KeyError, TypeError):
1294 
1295                 pass
1296 
1297             else:
1298 
1299                 if path_list is not None:
1300 
1301                     raise ValueError(
1302 
1303                         "env cannot contain 'PATH' and b'PATH' keys")
1304 
1305                 path_list = path_listb
1306 
1307 
1308 
1309             if path_list is not None and isinstance(path_list, bytes):
1310 
1311                 path_list = fsdecode(path_list)
1312 
1313 
1314 
1315     if path_list is None:
1316 
1317         path_list = defpath
1318 
1319     return path_list.split(pathsep)
1320 
1321 
1322 
1323 
1324 
1325 # Change environ to automatically call putenv(), unsetenv if they exist.
1326 
1327 from _collections_abc import MutableMapping
1328 
1329 
1330 
1331 class _Environ(MutableMapping):
1332 
1333     def __init__(self, data, encodekey, decodekey, encodevalue, decodevalue, putenv, unsetenv):
1334 
1335         self.encodekey = encodekey
1336 
1337         self.decodekey = decodekey
1338 
1339         self.encodevalue = encodevalue
1340 
1341         self.decodevalue = decodevalue
1342 
1343         self.putenv = putenv
1344 
1345         self.unsetenv = unsetenv
1346 
1347         self._data = data
1348 
1349 
1350 
1351     def __getitem__(self, key):
1352 
1353         try:
1354 
1355             value = self._data[self.encodekey(key)]
1356 
1357         except KeyError:
1358 
1359             # raise KeyError with the original key value
1360 
1361             raise KeyError(key) from None
1362 
1363         return self.decodevalue(value)
1364 
1365 
1366 
1367     def __setitem__(self, key, value):
1368 
1369         key = self.encodekey(key)
1370 
1371         value = self.encodevalue(value)
1372 
1373         self.putenv(key, value)
1374 
1375         self._data[key] = value
1376 
1377 
1378 
1379     def __delitem__(self, key):
1380 
1381         encodedkey = self.encodekey(key)
1382 
1383         self.unsetenv(encodedkey)
1384 
1385         try:
1386 
1387             del self._data[encodedkey]
1388 
1389         except KeyError:
1390 
1391             # raise KeyError with the original key value
1392 
1393             raise KeyError(key) from None
1394 
1395 
1396 
1397     def __iter__(self):
1398 
1399         # list() from dict object is an atomic operation
1400 
1401         keys = list(self._data)
1402 
1403         for key in keys:
1404 
1405             yield self.decodekey(key)
1406 
1407 
1408 
1409     def __len__(self):
1410 
1411         return len(self._data)
1412 
1413 
1414 
1415     def __repr__(self):
1416 
1417         return 'environ({{{}}})'.format(', '.join(
1418 
1419             ('{!r}: {!r}'.format(self.decodekey(key), self.decodevalue(value))
1420 
1421             for key, value in self._data.items())))
1422 
1423 
1424 
1425     def copy(self):
1426 
1427         return dict(self)
1428 
1429 
1430 
1431     def setdefault(self, key, value):
1432 
1433         if key not in self:
1434 
1435             self[key] = value
1436 
1437         return self[key]
1438 
1439 
1440 
1441 try:
1442 
1443     _putenv = putenv
1444 
1445 except NameError:
1446 
1447     _putenv = lambda key, value: None
1448 
1449 else:
1450 
1451     if "putenv" not in __all__:
1452 
1453         __all__.append("putenv")
1454 
1455 
1456 
1457 try:
1458 
1459     _unsetenv = unsetenv
1460 
1461 except NameError:
1462 
1463     _unsetenv = lambda key: _putenv(key, "")
1464 
1465 else:
1466 
1467     if "unsetenv" not in __all__:
1468 
1469         __all__.append("unsetenv")
1470 
1471 
1472 
1473 def _createenviron():
1474 
1475     if name == 'nt':
1476 
1477         # Where Env Var Names Must Be UPPERCASE
1478 
1479         def check_str(value):
1480 
1481             if not isinstance(value, str):
1482 
1483                 raise TypeError("str expected, not %s" % type(value).__name__)
1484 
1485             return value
1486 
1487         encode = check_str
1488 
1489         decode = str
1490 
1491         def encodekey(key):
1492 
1493             return encode(key).upper()
1494 
1495         data = {}
1496 
1497         for key, value in environ.items():
1498 
1499             data[encodekey(key)] = value
1500 
1501     else:
1502 
1503         # Where Env Var Names Can Be Mixed Case
1504 
1505         encoding = sys.getfilesystemencoding()
1506 
1507         def encode(value):
1508 
1509             if not isinstance(value, str):
1510 
1511                 raise TypeError("str expected, not %s" % type(value).__name__)
1512 
1513             return value.encode(encoding, 'surrogateescape')
1514 
1515         def decode(value):
1516 
1517             return value.decode(encoding, 'surrogateescape')
1518 
1519         encodekey = encode
1520 
1521         data = environ
1522 
1523     return _Environ(data,
1524 
1525         encodekey, decode,
1526 
1527         encode, decode,
1528 
1529         _putenv, _unsetenv)
1530 
1531 
1532 
1533 # unicode environ
1534 
1535 environ = _createenviron()
1536 
1537 del _createenviron
1538 
1539 
1540 
1541 
1542 
1543 def getenv(key, default=None):
1544 
1545     """Get an environment variable, return None if it doesn't exist.
1546 
1547     The optional second argument can specify an alternate default.
1548 
1549     key, default and the result are str."""
1550 
1551     return environ.get(key, default)
1552 
1553 
1554 
1555 supports_bytes_environ = (name != 'nt')
1556 
1557 __all__.extend(("getenv", "supports_bytes_environ"))
1558 
1559 
1560 
1561 if supports_bytes_environ:
1562 
1563     def _check_bytes(value):
1564 
1565         if not isinstance(value, bytes):
1566 
1567             raise TypeError("bytes expected, not %s" % type(value).__name__)
1568 
1569         return value
1570 
1571 
1572 
1573     # bytes environ
1574 
1575     environb = _Environ(environ._data,
1576 
1577         _check_bytes, bytes,
1578 
1579         _check_bytes, bytes,
1580 
1581         _putenv, _unsetenv)
1582 
1583     del _check_bytes
1584 
1585 
1586 
1587     def getenvb(key, default=None):
1588 
1589         """Get an environment variable, return None if it doesn't exist.
1590 
1591         The optional second argument can specify an alternate default.
1592 
1593         key, default and the result are bytes."""
1594 
1595         return environb.get(key, default)
1596 
1597 
1598 
1599     __all__.extend(("environb", "getenvb"))
1600 
1601 
1602 
1603 def _fscodec():
1604 
1605     encoding = sys.getfilesystemencoding()
1606 
1607     errors = sys.getfilesystemencodeerrors()
1608 
1609 
1610 
1611     def fsencode(filename):
1612 
1613         """Encode filename (an os.PathLike, bytes, or str) to the filesystem
1614 
1615         encoding with 'surrogateescape' error handler, return bytes unchanged.
1616 
1617         On Windows, use 'strict' error handler if the file system encoding is
1618 
1619         'mbcs' (which is the default encoding).
1620 
1621         """
1622 
1623         filename = fspath(filename)  # Does type-checking of `filename`.
1624 
1625         if isinstance(filename, str):
1626 
1627             return filename.encode(encoding, errors)
1628 
1629         else:
1630 
1631             return filename
1632 
1633 
1634 
1635     def fsdecode(filename):
1636 
1637         """Decode filename (an os.PathLike, bytes, or str) from the filesystem
1638 
1639         encoding with 'surrogateescape' error handler, return str unchanged. On
1640 
1641         Windows, use 'strict' error handler if the file system encoding is
1642 
1643         'mbcs' (which is the default encoding).
1644 
1645         """
1646 
1647         filename = fspath(filename)  # Does type-checking of `filename`.
1648 
1649         if isinstance(filename, bytes):
1650 
1651             return filename.decode(encoding, errors)
1652 
1653         else:
1654 
1655             return filename
1656 
1657 
1658 
1659     return fsencode, fsdecode
1660 
1661 
1662 
1663 fsencode, fsdecode = _fscodec()
1664 
1665 del _fscodec
1666 
1667 
1668 
1669 # Supply spawn*() (probably only for Unix)
1670 
1671 if _exists("fork") and not _exists("spawnv") and _exists("execv"):
1672 
1673 
1674 
1675     P_WAIT = 0
1676 
1677     P_NOWAIT = P_NOWAITO = 1
1678 
1679 
1680 
1681     __all__.extend(["P_WAIT", "P_NOWAIT", "P_NOWAITO"])
1682 
1683 
1684 
1685     # XXX Should we support P_DETACH?  I suppose it could fork()**2
1686 
1687     # and close the std I/O streams.  Also, P_OVERLAY is the same
1688 
1689     # as execv*()?
1690 
1691 
1692 
1693     def _spawnvef(mode, file, args, env, func):
1694 
1695         # Internal helper; func is the exec*() function to use
1696 
1697         if not isinstance(args, (tuple, list)):
1698 
1699             raise TypeError('argv must be a tuple or a list')
1700 
1701         if not args or not args[0]:
1702 
1703             raise ValueError('argv first element cannot be empty')
1704 
1705         pid = fork()
1706 
1707         if not pid:
1708 
1709             # Child
1710 
1711             try:
1712 
1713                 if env is None:
1714 
1715                     func(file, args)
1716 
1717                 else:
1718 
1719                     func(file, args, env)
1720 
1721             except:
1722 
1723                 _exit(127)
1724 
1725         else:
1726 
1727             # Parent
1728 
1729             if mode == P_NOWAIT:
1730 
1731                 return pid # Caller is responsible for waiting!
1732 
1733             while 1:
1734 
1735                 wpid, sts = waitpid(pid, 0)
1736 
1737                 if WIFSTOPPED(sts):
1738 
1739                     continue
1740 
1741                 elif WIFSIGNALED(sts):
1742 
1743                     return -WTERMSIG(sts)
1744 
1745                 elif WIFEXITED(sts):
1746 
1747                     return WEXITSTATUS(sts)
1748 
1749                 else:
1750 
1751                     raise OSError("Not stopped, signaled or exited???")
1752 
1753 
1754 
1755     def spawnv(mode, file, args):
1756 
1757         """spawnv(mode, file, args) -> integer
1758 
1759 
1760 
1761 Execute file with arguments from args in a subprocess.
1762 
1763 If mode == P_NOWAIT return the pid of the process.
1764 
1765 If mode == P_WAIT return the process's exit code if it exits normally;
1766 
1767 otherwise return -SIG, where SIG is the signal that killed it. """
1768 
1769         return _spawnvef(mode, file, args, None, execv)
1770 
1771 
1772 
1773     def spawnve(mode, file, args, env):
1774 
1775         """spawnve(mode, file, args, env) -> integer
1776 
1777 
1778 
1779 Execute file with arguments from args in a subprocess with the
1780 
1781 specified environment.
1782 
1783 If mode == P_NOWAIT return the pid of the process.
1784 
1785 If mode == P_WAIT return the process's exit code if it exits normally;
1786 
1787 otherwise return -SIG, where SIG is the signal that killed it. """
1788 
1789         return _spawnvef(mode, file, args, env, execve)
1790 
1791 
1792 
1793     # Note: spawnvp[e] isn't currently supported on Windows
1794 
1795 
1796 
1797     def spawnvp(mode, file, args):
1798 
1799         """spawnvp(mode, file, args) -> integer
1800 
1801 
1802 
1803 Execute file (which is looked for along $PATH) with arguments from
1804 
1805 args in a subprocess.
1806 
1807 If mode == P_NOWAIT return the pid of the process.
1808 
1809 If mode == P_WAIT return the process's exit code if it exits normally;
1810 
1811 otherwise return -SIG, where SIG is the signal that killed it. """
1812 
1813         return _spawnvef(mode, file, args, None, execvp)
1814 
1815 
1816 
1817     def spawnvpe(mode, file, args, env):
1818 
1819         """spawnvpe(mode, file, args, env) -> integer
1820 
1821 
1822 
1823 Execute file (which is looked for along $PATH) with arguments from
1824 
1825 args in a subprocess with the supplied environment.
1826 
1827 If mode == P_NOWAIT return the pid of the process.
1828 
1829 If mode == P_WAIT return the process's exit code if it exits normally;
1830 
1831 otherwise return -SIG, where SIG is the signal that killed it. """
1832 
1833         return _spawnvef(mode, file, args, env, execvpe)
1834 
1835 
1836 
1837 
1838 
1839     __all__.extend(["spawnv", "spawnve", "spawnvp", "spawnvpe"])
1840 
1841 
1842 
1843 
1844 
1845 if _exists("spawnv"):
1846 
1847     # These aren't supplied by the basic Windows code
1848 
1849     # but can be easily implemented in Python
1850 
1851 
1852 
1853     def spawnl(mode, file, *args):
1854 
1855         """spawnl(mode, file, *args) -> integer
1856 
1857 
1858 
1859 Execute file with arguments from args in a subprocess.
1860 
1861 If mode == P_NOWAIT return the pid of the process.
1862 
1863 If mode == P_WAIT return the process's exit code if it exits normally;
1864 
1865 otherwise return -SIG, where SIG is the signal that killed it. """
1866 
1867         return spawnv(mode, file, args)
1868 
1869 
1870 
1871     def spawnle(mode, file, *args):
1872 
1873         """spawnle(mode, file, *args, env) -> integer
1874 
1875 
1876 
1877 Execute file with arguments from args in a subprocess with the
1878 
1879 supplied environment.
1880 
1881 If mode == P_NOWAIT return the pid of the process.
1882 
1883 If mode == P_WAIT return the process's exit code if it exits normally;
1884 
1885 otherwise return -SIG, where SIG is the signal that killed it. """
1886 
1887         env = args[-1]
1888 
1889         return spawnve(mode, file, args[:-1], env)
1890 
1891 
1892 
1893 
1894 
1895     __all__.extend(["spawnl", "spawnle"])
1896 
1897 
1898 
1899 
1900 
1901 if _exists("spawnvp"):
1902 
1903     # At the moment, Windows doesn't implement spawnvp[e],
1904 
1905     # so it won't have spawnlp[e] either.
1906 
1907     def spawnlp(mode, file, *args):
1908 
1909         """spawnlp(mode, file, *args) -> integer
1910 
1911 
1912 
1913 Execute file (which is looked for along $PATH) with arguments from
1914 
1915 args in a subprocess with the supplied environment.
1916 
1917 If mode == P_NOWAIT return the pid of the process.
1918 
1919 If mode == P_WAIT return the process's exit code if it exits normally;
1920 
1921 otherwise return -SIG, where SIG is the signal that killed it. """
1922 
1923         return spawnvp(mode, file, args)
1924 
1925 
1926 
1927     def spawnlpe(mode, file, *args):
1928 
1929         """spawnlpe(mode, file, *args, env) -> integer
1930 
1931 
1932 
1933 Execute file (which is looked for along $PATH) with arguments from
1934 
1935 args in a subprocess with the supplied environment.
1936 
1937 If mode == P_NOWAIT return the pid of the process.
1938 
1939 If mode == P_WAIT return the process's exit code if it exits normally;
1940 
1941 otherwise return -SIG, where SIG is the signal that killed it. """
1942 
1943         env = args[-1]
1944 
1945         return spawnvpe(mode, file, args[:-1], env)
1946 
1947 
1948 
1949 
1950 
1951     __all__.extend(["spawnlp", "spawnlpe"])
1952 
1953 
1954 
1955 
1956 
1957 # Supply os.popen()
1958 
1959 def popen(cmd, mode="r", buffering=-1):
1960 
1961     if not isinstance(cmd, str):
1962 
1963         raise TypeError("invalid cmd type (%s, expected string)" % type(cmd))
1964 
1965     if mode not in ("r", "w"):
1966 
1967         raise ValueError("invalid mode %r" % mode)
1968 
1969     if buffering == 0 or buffering is None:
1970 
1971         raise ValueError("popen() does not support unbuffered streams")
1972 
1973     import subprocess, io
1974 
1975     if mode == "r":
1976 
1977         proc = subprocess.Popen(cmd,
1978 
1979                                 shell=True,
1980 
1981                                 stdout=subprocess.PIPE,
1982 
1983                                 bufsize=buffering)
1984 
1985         return _wrap_close(io.TextIOWrapper(proc.stdout), proc)
1986 
1987     else:
1988 
1989         proc = subprocess.Popen(cmd,
1990 
1991                                 shell=True,
1992 
1993                                 stdin=subprocess.PIPE,
1994 
1995                                 bufsize=buffering)
1996 
1997         return _wrap_close(io.TextIOWrapper(proc.stdin), proc)
1998 
1999 
2000 
2001 # Helper for popen() -- a proxy for a file whose close waits for the process
2002 
2003 class _wrap_close:
2004 
2005     def __init__(self, stream, proc):
2006 
2007         self._stream = stream
2008 
2009         self._proc = proc
2010 
2011     def close(self):
2012 
2013         self._stream.close()
2014 
2015         returncode = self._proc.wait()
2016 
2017         if returncode == 0:
2018 
2019             return None
2020 
2021         if name == 'nt':
2022 
2023             return returncode
2024 
2025         else:
2026 
2027             return returncode << 8  # Shift left to match old behavior
2028 
2029     def __enter__(self):
2030 
2031         return self
2032 
2033     def __exit__(self, *args):
2034 
2035         self.close()
2036 
2037     def __getattr__(self, name):
2038 
2039         return getattr(self._stream, name)
2040 
2041     def __iter__(self):
2042 
2043         return iter(self._stream)
2044 
2045 
2046 
2047 # Supply os.fdopen()
2048 
2049 def fdopen(fd, *args, **kwargs):
2050 
2051     if not isinstance(fd, int):
2052 
2053         raise TypeError("invalid fd type (%s, expected integer)" % type(fd))
2054 
2055     import io
2056 
2057     return io.open(fd, *args, **kwargs)
2058 
2059 
2060 
2061 
2062 
2063 # For testing purposes, make sure the function is available when the C
2064 
2065 # implementation exists.
2066 
2067 def _fspath(path):
2068 
2069     """Return the path representation of a path-like object.
2070 
2071 
2072 
2073     If str or bytes is passed in, it is returned unchanged. Otherwise the
2074 
2075     os.PathLike interface is used to get the path representation. If the
2076 
2077     path representation is not str or bytes, TypeError is raised. If the
2078 
2079     provided path is not str, bytes, or os.PathLike, TypeError is raised.
2080 
2081     """
2082 
2083     if isinstance(path, (str, bytes)):
2084 
2085         return path
2086 
2087 
2088 
2089     # Work from the object's type to match method resolution of other magic
2090 
2091     # methods.
2092 
2093     path_type = type(path)
2094 
2095     try:
2096 
2097         path_repr = path_type.__fspath__(path)
2098 
2099     except AttributeError:
2100 
2101         if hasattr(path_type, '__fspath__'):
2102 
2103             raise
2104 
2105         else:
2106 
2107             raise TypeError("expected str, bytes or os.PathLike object, "
2108 
2109                             "not " + path_type.__name__)
2110 
2111     if isinstance(path_repr, (str, bytes)):
2112 
2113         return path_repr
2114 
2115     else:
2116 
2117         raise TypeError("expected {}.__fspath__() to return str or bytes, "
2118 
2119                         "not {}".format(path_type.__name__,
2120 
2121                                         type(path_repr).__name__))
2122 
2123 
2124 
2125 # If there is no C implementation, make the pure Python version the
2126 
2127 # implementation as transparently as possible.
2128 
2129 if not _exists('fspath'):
2130 
2131     fspath = _fspath
2132 
2133     fspath.__name__ = "fspath"
2134 
2135 
2136 
2137 
2138 
2139 class PathLike(abc.ABC):
2140 
2141 
2142 
2143     """Abstract base class for implementing the file system path protocol."""
2144 
2145 
2146 
2147     @abc.abstractmethod
2148 
2149     def __fspath__(self):
2150 
2151         """Return the file system path representation of the object."""
2152 
2153         raise NotImplementedError
2154 
2155 
2156 
2157     @classmethod
2158 
2159     def __subclasshook__(cls, subclass):
2160 
2161         if cls is PathLike:
2162 
2163             return _check_methods(subclass, '__fspath__')
2164 
2165         return NotImplemented
View Code

参考资料:

https://docs.python.org/zh-cn/3.7/library/os.html#process-management

https://github.com/python/cpython/blob/3.7/Lib/os.py

原文地址:https://www.cnblogs.com/zhiminyu/p/12612527.html