Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
subprocess.py2258 linesDownload Raw Back to Lib
1# subprocess - Subprocesses with accessible I/O streams2#3# For more information about this module, see PEP 324.4#5# Copyright (c) 2003-2005 by Peter Astrand <astrand@lysator.liu.se>6#7# Licensed to PSF under a Contributor Agreement.8 9r"""Subprocesses with accessible I/O streams10 11This module allows you to spawn processes, connect to their12input/output/error pipes, and obtain their return codes.13 14For a complete description of this module see the Python documentation.15 16Main API17========18run(...): Runs a command, waits for it to complete, then returns a19          CompletedProcess instance.20Popen(...): A class for flexibly executing a command in a new process21 22Constants23---------24DEVNULL: Special value that indicates that os.devnull should be used25PIPE:    Special value that indicates a pipe should be created26STDOUT:  Special value that indicates that stderr should go to stdout27 28 29Older API30=========31call(...): Runs a command, waits for it to complete, then returns32    the return code.33check_call(...): Same as call() but raises CalledProcessError()34    if return code is not 035check_output(...): Same as check_call() but returns the contents of36    stdout instead of a return code37getoutput(...): Runs a command in the shell, waits for it to complete,38    then returns the output39getstatusoutput(...): Runs a command in the shell, waits for it to complete,40    then returns a (exitcode, output) tuple41"""42 43import builtins44import errno45import io46import locale47import os48import time49import signal50import sys51import threading52import warnings53import contextlib54from time import monotonic as _time55import types56 57try:58    import fcntl59except ImportError:60    fcntl = None61 62 63__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "getstatusoutput",64           "getoutput", "check_output", "run", "CalledProcessError", "DEVNULL",65           "SubprocessError", "TimeoutExpired", "CompletedProcess"]66           # NOTE: We intentionally exclude list2cmdline as it is67           # considered an internal implementation detail.  issue10838.68 69# use presence of msvcrt to detect Windows-like platforms (see bpo-8110)70try:71    import msvcrt72except ModuleNotFoundError:73    _mswindows = False74else:75    _mswindows = True76 77# some platforms do not support subprocesses78_can_fork_exec = sys.platform not in {"emscripten", "wasi", "ios", "tvos", "watchos"}79 80if _mswindows:81    import _winapi82    from _winapi import (CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP,  # noqa: F40183                         STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,84                         STD_ERROR_HANDLE, SW_HIDE,85                         STARTF_USESTDHANDLES, STARTF_USESHOWWINDOW,86                         STARTF_FORCEONFEEDBACK, STARTF_FORCEOFFFEEDBACK,87                         ABOVE_NORMAL_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS,88                         HIGH_PRIORITY_CLASS, IDLE_PRIORITY_CLASS,89                         NORMAL_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS,90                         CREATE_NO_WINDOW, DETACHED_PROCESS,91                         CREATE_DEFAULT_ERROR_MODE, CREATE_BREAKAWAY_FROM_JOB)92 93    __all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP",94                    "STD_INPUT_HANDLE", "STD_OUTPUT_HANDLE",95                    "STD_ERROR_HANDLE", "SW_HIDE",96                    "STARTF_USESTDHANDLES", "STARTF_USESHOWWINDOW",97                    "STARTF_FORCEONFEEDBACK", "STARTF_FORCEOFFFEEDBACK",98                    "STARTUPINFO",99                    "ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS",100                    "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS",101                    "NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS",102                    "CREATE_NO_WINDOW", "DETACHED_PROCESS",103                    "CREATE_DEFAULT_ERROR_MODE", "CREATE_BREAKAWAY_FROM_JOB"])104else:105    if _can_fork_exec:106        from _posixsubprocess import fork_exec as _fork_exec107        # used in methods that are called by __del__108        class _del_safe:109            waitpid = os.waitpid110            waitstatus_to_exitcode = os.waitstatus_to_exitcode111            WIFSTOPPED = os.WIFSTOPPED112            WSTOPSIG = os.WSTOPSIG113            WNOHANG = os.WNOHANG114            ECHILD = errno.ECHILD115    else:116        class _del_safe:117            waitpid = None118            waitstatus_to_exitcode = None119            WIFSTOPPED = None120            WSTOPSIG = None121            WNOHANG = None122            ECHILD = errno.ECHILD123 124    import select125    import selectors126 127 128# Exception classes used by this module.129class SubprocessError(Exception): pass130 131 132class CalledProcessError(SubprocessError):133    """Raised when run() is called with check=True and the process134    returns a non-zero exit status.135 136    Attributes:137      cmd, returncode, stdout, stderr, output138    """139    def __init__(self, returncode, cmd, output=None, stderr=None):140        self.returncode = returncode141        self.cmd = cmd142        self.output = output143        self.stderr = stderr144 145    def __str__(self):146        if self.returncode and self.returncode < 0:147            try:148                return "Command '%s' died with %r." % (149                        self.cmd, signal.Signals(-self.returncode))150            except ValueError:151                return "Command '%s' died with unknown signal %d." % (152                        self.cmd, -self.returncode)153        else:154            return "Command '%s' returned non-zero exit status %d." % (155                    self.cmd, self.returncode)156 157    @property158    def stdout(self):159        """Alias for output attribute, to match stderr"""160        return self.output161 162    @stdout.setter163    def stdout(self, value):164        # There's no obvious reason to set this, but allow it anyway so165        # .stdout is a transparent alias for .output166        self.output = value167 168 169class TimeoutExpired(SubprocessError):170    """This exception is raised when the timeout expires while waiting for a171    child process.172 173    Attributes:174        cmd, output, stdout, stderr, timeout175    """176    def __init__(self, cmd, timeout, output=None, stderr=None):177        self.cmd = cmd178        self.timeout = timeout179        self.output = output180        self.stderr = stderr181 182    def __str__(self):183        return ("Command '%s' timed out after %s seconds" %184                (self.cmd, self.timeout))185 186    @property187    def stdout(self):188        return self.output189 190    @stdout.setter191    def stdout(self, value):192        # There's no obvious reason to set this, but allow it anyway so193        # .stdout is a transparent alias for .output194        self.output = value195 196 197if _mswindows:198    class STARTUPINFO:199        def __init__(self, *, dwFlags=0, hStdInput=None, hStdOutput=None,200                     hStdError=None, wShowWindow=0, lpAttributeList=None):201            self.dwFlags = dwFlags202            self.hStdInput = hStdInput203            self.hStdOutput = hStdOutput204            self.hStdError = hStdError205            self.wShowWindow = wShowWindow206            self.lpAttributeList = lpAttributeList or {"handle_list": []}207 208        def copy(self):209            attr_list = self.lpAttributeList.copy()210            if 'handle_list' in attr_list:211                attr_list['handle_list'] = list(attr_list['handle_list'])212 213            return STARTUPINFO(dwFlags=self.dwFlags,214                               hStdInput=self.hStdInput,215                               hStdOutput=self.hStdOutput,216                               hStdError=self.hStdError,217                               wShowWindow=self.wShowWindow,218                               lpAttributeList=attr_list)219 220 221    class Handle(int):222        closed = False223 224        def Close(self, CloseHandle=_winapi.CloseHandle):225            if not self.closed:226                self.closed = True227                CloseHandle(self)228 229        def Detach(self):230            if not self.closed:231                self.closed = True232                return int(self)233            raise ValueError("already closed")234 235        def __repr__(self):236            return "%s(%d)" % (self.__class__.__name__, int(self))237 238        __del__ = Close239else:240    # When select or poll has indicated that the file is writable,241    # we can write up to _PIPE_BUF bytes without risk of blocking.242    # POSIX defines PIPE_BUF as >= 512.243    _PIPE_BUF = getattr(select, 'PIPE_BUF', 512)244 245    # poll/select have the advantage of not requiring any extra file246    # descriptor, contrarily to epoll/kqueue (also, they require a single247    # syscall).248    if hasattr(selectors, 'PollSelector'):249        _PopenSelector = selectors.PollSelector250    else:251        _PopenSelector = selectors.SelectSelector252 253 254if _mswindows:255    # On Windows we just need to close `Popen._handle` when we no longer need256    # it, so that the kernel can free it. `Popen._handle` gets closed257    # implicitly when the `Popen` instance is finalized (see `Handle.__del__`,258    # which is calling `CloseHandle` as requested in [1]), so there is nothing259    # for `_cleanup` to do.260    #261    # [1] https://docs.microsoft.com/en-us/windows/desktop/ProcThread/262    # creating-processes263    _active = None264 265    def _cleanup():266        pass267else:268    # This lists holds Popen instances for which the underlying process had not269    # exited at the time its __del__ method got called: those processes are270    # wait()ed for synchronously from _cleanup() when a new Popen object is271    # created, to avoid zombie processes.272    _active = []273 274    def _cleanup():275        if _active is None:276            return277        for inst in _active[:]:278            res = inst._internal_poll(_deadstate=sys.maxsize)279            if res is not None:280                try:281                    _active.remove(inst)282                except ValueError:283                    # This can happen if two threads create a new Popen instance.284                    # It's harmless that it was already removed, so ignore.285                    pass286 287PIPE = -1288STDOUT = -2289DEVNULL = -3290 291 292# XXX This function is only used by multiprocessing and the test suite,293# but it's here so that it can be imported when Python is compiled without294# threads.295 296def _optim_args_from_interpreter_flags():297    """Return a list of command-line arguments reproducing the current298    optimization settings in sys.flags."""299    args = []300    value = sys.flags.optimize301    if value > 0:302        args.append('-' + 'O' * value)303    return args304 305 306def _args_from_interpreter_flags():307    """Return a list of command-line arguments reproducing the current308    settings in sys.flags, sys.warnoptions and sys._xoptions."""309    flag_opt_map = {310        'debug': 'd',311        # 'inspect': 'i',312        # 'interactive': 'i',313        'dont_write_bytecode': 'B',314        'no_site': 'S',315        'verbose': 'v',316        'bytes_warning': 'b',317        'quiet': 'q',318        # -O is handled in _optim_args_from_interpreter_flags()319    }320    args = _optim_args_from_interpreter_flags()321    for flag, opt in flag_opt_map.items():322        v = getattr(sys.flags, flag)323        if v > 0:324            args.append('-' + opt * v)325 326    if sys.flags.isolated:327        args.append('-I')328    else:329        if sys.flags.ignore_environment:330            args.append('-E')331        if sys.flags.no_user_site:332            args.append('-s')333        if sys.flags.safe_path:334            args.append('-P')335 336    # -W options337    warnopts = sys.warnoptions[:]338    xoptions = getattr(sys, '_xoptions', {})339    bytes_warning = sys.flags.bytes_warning340    dev_mode = sys.flags.dev_mode341 342    if bytes_warning > 1:343        warnopts.remove("error::BytesWarning")344    elif bytes_warning:345        warnopts.remove("default::BytesWarning")346    if dev_mode:347        warnopts.remove('default')348    for opt in warnopts:349        args.append('-W' + opt)350 351    # -X options352    if dev_mode:353        args.extend(('-X', 'dev'))354    for opt in sorted(xoptions):355        if opt == 'dev':356            # handled above via sys.flags.dev_mode357            continue358        value = xoptions[opt]359        if value is True:360            arg = opt361        else:362            arg = '%s=%s' % (opt, value)363        args.extend(('-X', arg))364 365    return args366 367 368def _text_encoding():369    # Return default text encoding and emit EncodingWarning if370    # sys.flags.warn_default_encoding is true.371    if sys.flags.warn_default_encoding:372        f = sys._getframe()373        filename = f.f_code.co_filename374        stacklevel = 2375        while f := f.f_back:376            if f.f_code.co_filename != filename:377                break378            stacklevel += 1379        warnings.warn("'encoding' argument not specified.",380                      EncodingWarning, stacklevel)381 382    if sys.flags.utf8_mode:383        return "utf-8"384    else:385        return locale.getencoding()386 387 388def call(*popenargs, timeout=None, **kwargs):389    """Run command with arguments.  Wait for command to complete or390    for timeout seconds, then return the returncode attribute.391 392    The arguments are the same as for the Popen constructor.  Example:393 394    retcode = call(["ls", "-l"])395    """396    with Popen(*popenargs, **kwargs) as p:397        try:398            return p.wait(timeout=timeout)399        except:  # Including KeyboardInterrupt, wait handled that.400            p.kill()401            # We don't call p.wait() again as p.__exit__ does that for us.402            raise403 404 405def check_call(*popenargs, **kwargs):406    """Run command with arguments.  Wait for command to complete.  If407    the exit code was zero then return, otherwise raise408    CalledProcessError.  The CalledProcessError object will have the409    return code in the returncode attribute.410 411    The arguments are the same as for the call function.  Example:412 413    check_call(["ls", "-l"])414    """415    retcode = call(*popenargs, **kwargs)416    if retcode:417        cmd = kwargs.get("args")418        if cmd is None:419            cmd = popenargs[0]420        raise CalledProcessError(retcode, cmd)421    return 0422 423 424def check_output(*popenargs, timeout=None, **kwargs):425    r"""Run command with arguments and return its output.426 427    If the exit code was non-zero it raises a CalledProcessError.  The428    CalledProcessError object will have the return code in the returncode429    attribute and output in the output attribute.430 431    The arguments are the same as for the Popen constructor.  Example:432 433    >>> check_output(["ls", "-l", "/dev/null"])434    b'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'435 436    The stdout argument is not allowed as it is used internally.437    To capture standard error in the result, use stderr=STDOUT.438 439    >>> check_output(["/bin/sh", "-c",440    ...               "ls -l non_existent_file ; exit 0"],441    ...              stderr=STDOUT)442    b'ls: non_existent_file: No such file or directory\n'443 444    There is an additional optional argument, "input", allowing you to445    pass a string to the subprocess's stdin.  If you use this argument446    you may not also use the Popen constructor's "stdin" argument, as447    it too will be used internally.  Example:448 449    >>> check_output(["sed", "-e", "s/foo/bar/"],450    ...              input=b"when in the course of fooman events\n")451    b'when in the course of barman events\n'452 453    By default, all communication is in bytes, and therefore any "input"454    should be bytes, and the return value will be bytes.  If in text mode,455    any "input" should be a string, and the return value will be a string456    decoded according to locale encoding, or by "encoding" if set. Text mode457    is triggered by setting any of text, encoding, errors or universal_newlines.458    """459    for kw in ('stdout', 'check'):460        if kw in kwargs:461            raise ValueError(f'{kw} argument not allowed, it will be overridden.')462 463    if 'input' in kwargs and kwargs['input'] is None:464        # Explicitly passing input=None was previously equivalent to passing an465        # empty string. That is maintained here for backwards compatibility.466        if kwargs.get('universal_newlines') or kwargs.get('text') or kwargs.get('encoding') \467                or kwargs.get('errors'):468            empty = ''469        else:470            empty = b''471        kwargs['input'] = empty472 473    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,474               **kwargs).stdout475 476 477class CompletedProcess(object):478    """A process that has finished running.479 480    This is returned by run().481 482    Attributes:483      args: The list or str args passed to run().484      returncode: The exit code of the process, negative for signals.485      stdout: The standard output (None if not captured).486      stderr: The standard error (None if not captured).487    """488    def __init__(self, args, returncode, stdout=None, stderr=None):489        self.args = args490        self.returncode = returncode491        self.stdout = stdout492        self.stderr = stderr493 494    def __repr__(self):495        args = ['args={!r}'.format(self.args),496                'returncode={!r}'.format(self.returncode)]497        if self.stdout is not None:498            args.append('stdout={!r}'.format(self.stdout))499        if self.stderr is not None:500            args.append('stderr={!r}'.format(self.stderr))501        return "{}({})".format(type(self).__name__, ', '.join(args))502 503    __class_getitem__ = classmethod(types.GenericAlias)504 505 506    def check_returncode(self):507        """Raise CalledProcessError if the exit code is non-zero."""508        if self.returncode:509            raise CalledProcessError(self.returncode, self.args, self.stdout,510                                     self.stderr)511 512 513def run(*popenargs,514        input=None, capture_output=False, timeout=None, check=False, **kwargs):515    """Run command with arguments and return a CompletedProcess instance.516 517    The returned instance will have attributes args, returncode, stdout and518    stderr. By default, stdout and stderr are not captured, and those attributes519    will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them,520    or pass capture_output=True to capture both.521 522    If check is True and the exit code was non-zero, it raises a523    CalledProcessError. The CalledProcessError object will have the return code524    in the returncode attribute, and output & stderr attributes if those streams525    were captured.526 527    If timeout (seconds) is given and the process takes too long,528     a TimeoutExpired exception will be raised.529 530    There is an optional argument "input", allowing you to531    pass bytes or a string to the subprocess's stdin.  If you use this argument532    you may not also use the Popen constructor's "stdin" argument, as533    it will be used internally.534 535    By default, all communication is in bytes, and therefore any "input" should536    be bytes, and the stdout and stderr will be bytes. If in text mode, any537    "input" should be a string, and stdout and stderr will be strings decoded538    according to locale encoding, or by "encoding" if set. Text mode is539    triggered by setting any of text, encoding, errors or universal_newlines.540 541    The other arguments are the same as for the Popen constructor.542    """543    if input is not None:544        if kwargs.get('stdin') is not None:545            raise ValueError('stdin and input arguments may not both be used.')546        kwargs['stdin'] = PIPE547 548    if capture_output:549        if kwargs.get('stdout') is not None or kwargs.get('stderr') is not None:550            raise ValueError('stdout and stderr arguments may not be used '551                             'with capture_output.')552        kwargs['stdout'] = PIPE553        kwargs['stderr'] = PIPE554 555    with Popen(*popenargs, **kwargs) as process:556        try:557            stdout, stderr = process.communicate(input, timeout=timeout)558        except TimeoutExpired as exc:559            process.kill()560            if _mswindows:561                # Windows accumulates the output in a single blocking562                # read() call run on child threads, with the timeout563                # being done in a join() on those threads.  communicate()564                # _after_ kill() is required to collect that and add it565                # to the exception.566                exc.stdout, exc.stderr = process.communicate()567            else:568                # POSIX _communicate already populated the output so569                # far into the TimeoutExpired exception.570                process.wait()571            raise572        except:  # Including KeyboardInterrupt, communicate handled that.573            process.kill()574            # We don't call process.wait() as .__exit__ does that for us.575            raise576        retcode = process.poll()577        if check and retcode:578            raise CalledProcessError(retcode, process.args,579                                     output=stdout, stderr=stderr)580    return CompletedProcess(process.args, retcode, stdout, stderr)581 582 583def list2cmdline(seq):584    """585    Translate a sequence of arguments into a command line586    string, using the same rules as the MS C runtime:587 588    1) Arguments are delimited by white space, which is either a589       space or a tab.590 591    2) A string surrounded by double quotation marks is592       interpreted as a single argument, regardless of white space593       contained within.  A quoted string can be embedded in an594       argument.595 596    3) A double quotation mark preceded by a backslash is597       interpreted as a literal double quotation mark.598 599    4) Backslashes are interpreted literally, unless they600       immediately precede a double quotation mark.601 602    5) If backslashes immediately precede a double quotation mark,603       every pair of backslashes is interpreted as a literal604       backslash.  If the number of backslashes is odd, the last605       backslash escapes the next double quotation mark as606       described in rule 3.607    """608 609    # See610    # http://msdn.microsoft.com/en-us/library/17w5ykft.aspx611    # or search http://msdn.microsoft.com for612    # "Parsing C++ Command-Line Arguments"613    result = []614    needquote = False615    for arg in map(os.fsdecode, seq):616        bs_buf = []617 618        # Add a space to separate this argument from the others619        if result:620            result.append(' ')621 622        needquote = (" " in arg) or ("\t" in arg) or not arg623        if needquote:624            result.append('"')625 626        for c in arg:627            if c == '\\':628                # Don't know if we need to double yet.629                bs_buf.append(c)630            elif c == '"':631                # Double backslashes.632                result.append('\\' * len(bs_buf)*2)633                bs_buf = []634                result.append('\\"')635            else:636                # Normal char637                if bs_buf:638                    result.extend(bs_buf)639                    bs_buf = []640                result.append(c)641 642        # Add remaining backslashes, if any.643        if bs_buf:644            result.extend(bs_buf)645 646        if needquote:647            result.extend(bs_buf)648            result.append('"')649 650    return ''.join(result)651 652 653# Various tools for executing commands and looking at their output and status.654#655 656def getstatusoutput(cmd, *, encoding=None, errors=None):657    """Return (exitcode, output) of executing cmd in a shell.658 659    Execute the string 'cmd' in a shell with 'check_output' and660    return a 2-tuple (status, output). The locale encoding is used661    to decode the output and process newlines.662 663    A trailing newline is stripped from the output.664    The exit status for the command can be interpreted665    according to the rules for the function 'wait'. Example:666 667    >>> import subprocess668    >>> subprocess.getstatusoutput('ls /bin/ls')669    (0, '/bin/ls')670    >>> subprocess.getstatusoutput('cat /bin/junk')671    (1, 'cat: /bin/junk: No such file or directory')672    >>> subprocess.getstatusoutput('/bin/junk')673    (127, 'sh: /bin/junk: not found')674    >>> subprocess.getstatusoutput('/bin/kill $$')675    (-15, '')676    """677    try:678        data = check_output(cmd, shell=True, text=True, stderr=STDOUT,679                            encoding=encoding, errors=errors)680        exitcode = 0681    except CalledProcessError as ex:682        data = ex.output683        exitcode = ex.returncode684    if data[-1:] == '\n':685        data = data[:-1]686    return exitcode, data687 688def getoutput(cmd, *, encoding=None, errors=None):689    """Return output (stdout or stderr) of executing cmd in a shell.690 691    Like getstatusoutput(), except the exit status is ignored and the return692    value is a string containing the command's output.  Example:693 694    >>> import subprocess695    >>> subprocess.getoutput('ls /bin/ls')696    '/bin/ls'697    """698    return getstatusoutput(cmd, encoding=encoding, errors=errors)[1]699 700 701 702def _use_posix_spawn():703    """Check if posix_spawn() can be used for subprocess.704 705    subprocess requires a posix_spawn() implementation that properly reports706    errors to the parent process, & sets errno on the following failures:707 708    * Process attribute actions failed.709    * File actions failed.710    * exec() failed.711 712    Prefer an implementation which can use vfork() in some cases for best713    performance.714    """715    if _mswindows or not hasattr(os, 'posix_spawn'):716        # os.posix_spawn() is not available717        return False718 719    if ((_env := os.environ.get('_PYTHON_SUBPROCESS_USE_POSIX_SPAWN')) in ('0', '1')):720        return bool(int(_env))721 722    if sys.platform in ('darwin', 'sunos5'):723        # posix_spawn() is a syscall on both macOS and Solaris,724        # and properly reports errors725        return True726 727    # Check libc name and runtime libc version728    try:729        ver = os.confstr('CS_GNU_LIBC_VERSION')730        # parse 'glibc 2.28' as ('glibc', (2, 28))731        parts = ver.split(maxsplit=1)732        if len(parts) != 2:733            # reject unknown format734            raise ValueError735        libc = parts[0]736        version = tuple(map(int, parts[1].split('.')))737 738        if sys.platform == 'linux' and libc == 'glibc' and version >= (2, 24):739            # glibc 2.24 has a new Linux posix_spawn implementation using vfork740            # which properly reports errors to the parent process.741            return True742        # Note: Don't use the implementation in earlier glibc because it doesn't743        # use vfork (even if glibc 2.26 added a pipe to properly report errors744        # to the parent process).745    except (AttributeError, ValueError, OSError):746        # os.confstr() or CS_GNU_LIBC_VERSION value not available747        pass748 749    # By default, assume that posix_spawn() does not properly report errors.750    return False751 752 753# These are primarily fail-safe knobs for negatives. A True value does not754# guarantee the given libc/syscall API will be used.755_USE_POSIX_SPAWN = _use_posix_spawn()756_HAVE_POSIX_SPAWN_CLOSEFROM = hasattr(os, 'POSIX_SPAWN_CLOSEFROM')757 758 759class Popen:760    """ Execute a child program in a new process.761 762    For a complete description of the arguments see the Python documentation.763 764    Arguments:765      args: A string, or a sequence of program arguments.766 767      bufsize: supplied as the buffering argument to the open() function when768          creating the stdin/stdout/stderr pipe file objects769 770      executable: A replacement program to execute.771 772      stdin, stdout and stderr: These specify the executed programs' standard773          input, standard output and standard error file handles, respectively.774 775      preexec_fn: (POSIX only) An object to be called in the child process776          just before the child is executed.777 778      close_fds: Controls closing or inheriting of file descriptors.779 780      shell: If true, the command will be executed through the shell.781 782      cwd: Sets the current directory before the child is executed.783 784      env: Defines the environment variables for the new process.785 786      text: If true, decode stdin, stdout and stderr using the given encoding787          (if set) or the system default otherwise.788 789      universal_newlines: Alias of text, provided for backwards compatibility.790 791      startupinfo and creationflags (Windows only)792 793      restore_signals (POSIX only)794 795      start_new_session (POSIX only)796 797      process_group (POSIX only)798 799      group (POSIX only)800 801      extra_groups (POSIX only)802 803      user (POSIX only)804 805      umask (POSIX only)806 807      pass_fds (POSIX only)808 809      encoding and errors: Text mode encoding and error handling to use for810          file objects stdin, stdout and stderr.811 812    Attributes:813        stdin, stdout, stderr, pid, returncode814    """815    _child_created = False  # Set here since __del__ checks it816 817    def __init__(self, args, bufsize=-1, executable=None,818                 stdin=None, stdout=None, stderr=None,819                 preexec_fn=None, close_fds=True,820                 shell=False, cwd=None, env=None, universal_newlines=None,821                 startupinfo=None, creationflags=0,822                 restore_signals=True, start_new_session=False,823                 pass_fds=(), *, user=None, group=None, extra_groups=None,824                 encoding=None, errors=None, text=None, umask=-1, pipesize=-1,825                 process_group=None):826        """Create new Popen instance."""827        if not _can_fork_exec:828            raise OSError(829                errno.ENOTSUP, f"{sys.platform} does not support processes."830            )831 832        _cleanup()833        # Held while anything is calling waitpid before returncode has been834        # updated to prevent clobbering returncode if wait() or poll() are835        # called from multiple threads at once.  After acquiring the lock,836        # code must re-check self.returncode to see if another thread just837        # finished a waitpid() call.838        self._waitpid_lock = threading.Lock()839 840        self._input = None841        self._communication_started = False842        if bufsize is None:843            bufsize = -1  # Restore default844        if not isinstance(bufsize, int):845            raise TypeError("bufsize must be an integer")846 847        if stdout is STDOUT:848            raise ValueError("STDOUT can only be used for stderr")849 850        if pipesize is None:851            pipesize = -1  # Restore default852        if not isinstance(pipesize, int):853            raise TypeError("pipesize must be an integer")854 855        if _mswindows:856            if preexec_fn is not None:857                raise ValueError("preexec_fn is not supported on Windows "858                                 "platforms")859        else:860            # POSIX861            if pass_fds and not close_fds:862                warnings.warn("pass_fds overriding close_fds.", RuntimeWarning)863                close_fds = True864            if startupinfo is not None:865                raise ValueError("startupinfo is only supported on Windows "866                                 "platforms")867            if creationflags != 0:868                raise ValueError("creationflags is only supported on Windows "869                                 "platforms")870 871        self.args = args872        self.stdin = None873        self.stdout = None874        self.stderr = None875        self.pid = None876        self.returncode = None877        self.encoding = encoding878        self.errors = errors879        self.pipesize = pipesize880 881        # Validate the combinations of text and universal_newlines882        if (text is not None and universal_newlines is not None883            and bool(universal_newlines) != bool(text)):884            raise SubprocessError('Cannot disambiguate when both text '885                                  'and universal_newlines are supplied but '886                                  'different. Pass one or the other.')887 888        self.text_mode = encoding or errors or text or universal_newlines889        if self.text_mode and encoding is None:890            self.encoding = encoding = _text_encoding()891 892        # How long to resume waiting on a child after the first ^C.893        # There is no right value for this.  The purpose is to be polite894        # yet remain good for interactive users trying to exit a tool.895        self._sigint_wait_secs = 0.25  # 1/xkcd221.getRandomNumber()896 897        self._closed_child_pipe_fds = False898 899        if self.text_mode:900            if bufsize == 1:901                line_buffering = True902                # Use the default buffer size for the underlying binary streams903                # since they don't support line buffering.904                bufsize = -1905            else:906                line_buffering = False907 908        if process_group is None:909            process_group = -1  # The internal APIs are int-only910 911        gid = None912        if group is not None:913            if not hasattr(os, 'setregid'):914                raise ValueError("The 'group' parameter is not supported on the "915                                 "current platform")916 917            elif isinstance(group, str):918                try:919                    import grp920                except ImportError:921                    raise ValueError("The group parameter cannot be a string "922                                     "on systems without the grp module")923 924                gid = grp.getgrnam(group).gr_gid925            elif isinstance(group, int):926                gid = group927            else:928                raise TypeError("Group must be a string or an integer, not {}"929                                .format(type(group)))930 931            if gid < 0:932                raise ValueError(f"Group ID cannot be negative, got {gid}")933 934        gids = None935        if extra_groups is not None:936            if not hasattr(os, 'setgroups'):937                raise ValueError("The 'extra_groups' parameter is not "938                                 "supported on the current platform")939 940            elif isinstance(extra_groups, str):941                raise ValueError("Groups must be a list, not a string")942 943            gids = []944            for extra_group in extra_groups:945                if isinstance(extra_group, str):946                    try:947                        import grp948                    except ImportError:949                        raise ValueError("Items in extra_groups cannot be "950                                         "strings on systems without the "951                                         "grp module")952 953                    gids.append(grp.getgrnam(extra_group).gr_gid)954                elif isinstance(extra_group, int):955                    gids.append(extra_group)956                else:957                    raise TypeError("Items in extra_groups must be a string "958                                    "or integer, not {}"959                                    .format(type(extra_group)))960 961            # make sure that the gids are all positive here so we can do less962            # checking in the C code963            for gid_check in gids:964                if gid_check < 0:965                    raise ValueError(f"Group ID cannot be negative, got {gid_check}")966 967        uid = None968        if user is not None:969            if not hasattr(os, 'setreuid'):970                raise ValueError("The 'user' parameter is not supported on "971                                 "the current platform")972 973            elif isinstance(user, str):974                try:975                    import pwd976                except ImportError:977                    raise ValueError("The user parameter cannot be a string "978                                     "on systems without the pwd module")979                uid = pwd.getpwnam(user).pw_uid980            elif isinstance(user, int):981                uid = user982            else:983                raise TypeError("User must be a string or an integer")984 985            if uid < 0:986                raise ValueError(f"User ID cannot be negative, got {uid}")987 988        # Input and output objects. The general principle is like989        # this:990        #991        # Parent                   Child992        # ------                   -----993        # p2cwrite   ---stdin--->  p2cread994        # c2pread    <--stdout---  c2pwrite995        # errread    <--stderr---  errwrite996        #997        # On POSIX, the child objects are file descriptors.  On998        # Windows, these are Windows file handles.  The parent objects999        # are file descriptors on both platforms.  The parent objects1000        # are -1 when not using PIPEs. The child objects are -11001        # when not redirecting.1002 1003        (p2cread, p2cwrite,1004         c2pread, c2pwrite,1005         errread, errwrite) = self._get_handles(stdin, stdout, stderr)1006 1007        # From here on, raising exceptions may cause file descriptor leakage1008 1009        # We wrap OS handles *before* launching the child, otherwise a1010        # quickly terminating child could make our fds unwrappable1011        # (see #8458).1012 1013        if _mswindows:1014            if p2cwrite != -1:1015                p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0)1016            if c2pread != -1:1017                c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0)1018            if errread != -1:1019                errread = msvcrt.open_osfhandle(errread.Detach(), 0)1020 1021        try:1022            if p2cwrite != -1:1023                self.stdin = io.open(p2cwrite, 'wb', bufsize)1024                if self.text_mode:1025                    self.stdin = io.TextIOWrapper(self.stdin, write_through=True,1026                            line_buffering=line_buffering,1027                            encoding=encoding, errors=errors)1028            if c2pread != -1:1029                self.stdout = io.open(c2pread, 'rb', bufsize)1030                if self.text_mode:1031                    self.stdout = io.TextIOWrapper(self.stdout,1032                            encoding=encoding, errors=errors)1033            if errread != -1:1034                self.stderr = io.open(errread, 'rb', bufsize)1035                if self.text_mode:1036                    self.stderr = io.TextIOWrapper(self.stderr,1037                            encoding=encoding, errors=errors)1038 1039            self._execute_child(args, executable, preexec_fn, close_fds,1040                                pass_fds, cwd, env,1041                                startupinfo, creationflags, shell,1042                                p2cread, p2cwrite,1043                                c2pread, c2pwrite,1044                                errread, errwrite,1045                                restore_signals,1046                                gid, gids, uid, umask,1047                                start_new_session, process_group)1048        except:1049            # Cleanup if the child failed starting.1050            for f in filter(None, (self.stdin, self.stdout, self.stderr)):1051                try:1052                    f.close()1053                except OSError:1054                    pass  # Ignore EBADF or other errors.1055 1056            if not self._closed_child_pipe_fds:1057                to_close = []1058                if stdin == PIPE:1059                    to_close.append(p2cread)1060                if stdout == PIPE:1061                    to_close.append(c2pwrite)1062                if stderr == PIPE:1063                    to_close.append(errwrite)1064                if hasattr(self, '_devnull'):1065                    to_close.append(self._devnull)1066                for fd in to_close:1067                    try:1068                        if _mswindows and isinstance(fd, Handle):1069                            fd.Close()1070                        else:1071                            os.close(fd)1072                    except OSError:1073                        pass1074 1075            raise1076 1077    def __repr__(self):1078        obj_repr = (1079            f"<{self.__class__.__name__}: "1080            f"returncode: {self.returncode} args: {self.args!r}>"1081        )1082        if len(obj_repr) > 80:1083            obj_repr = obj_repr[:76] + "...>"1084        return obj_repr1085 1086    __class_getitem__ = classmethod(types.GenericAlias)1087 1088    @property1089    def universal_newlines(self):1090        # universal_newlines as retained as an alias of text_mode for API1091        # compatibility. bpo-317561092        return self.text_mode1093 1094    @universal_newlines.setter1095    def universal_newlines(self, universal_newlines):1096        self.text_mode = bool(universal_newlines)1097 1098    def _translate_newlines(self, data, encoding, errors):1099        data = data.decode(encoding, errors)1100        return data.replace("\r\n", "\n").replace("\r", "\n")1101 1102    def __enter__(self):1103        return self1104 1105    def __exit__(self, exc_type, value, traceback):1106        if self.stdout:1107            self.stdout.close()1108        if self.stderr:1109            self.stderr.close()1110        try:  # Flushing a BufferedWriter may raise an error1111            if self.stdin:1112                self.stdin.close()1113        finally:1114            if exc_type == KeyboardInterrupt:1115                # https://bugs.python.org/issue259421116                # In the case of a KeyboardInterrupt we assume the SIGINT1117                # was also already sent to our child processes.  We can't1118                # block indefinitely as that is not user friendly.1119                # If we have not already waited a brief amount of time in1120                # an interrupted .wait() or .communicate() call, do so here1121                # for consistency.1122                if self._sigint_wait_secs > 0:1123                    try:1124                        self._wait(timeout=self._sigint_wait_secs)1125                    except TimeoutExpired:1126                        pass1127                self._sigint_wait_secs = 0  # Note that this has been done.1128            else:1129                # Wait for the process to terminate, to avoid zombies.1130                self.wait()1131 1132    def __del__(self, _maxsize=sys.maxsize, _warn=warnings.warn):1133        if not self._child_created:1134            # We didn't get to successfully create a child process.1135            return1136        if self.returncode is None:1137            # Not reading subprocess exit status creates a zombie process which1138            # is only destroyed at the parent python process exit1139            _warn("subprocess %s is still running" % self.pid,1140                  ResourceWarning, source=self)1141        # In case the child hasn't been waited on, check if it's done.1142        self._internal_poll(_deadstate=_maxsize)1143        if self.returncode is None and _active is not None:1144            # Child is still running, keep us alive until we can wait on it.1145            _active.append(self)1146 1147    def _get_devnull(self):1148        if not hasattr(self, '_devnull'):1149            self._devnull = os.open(os.devnull, os.O_RDWR)1150        return self._devnull1151 1152    def _stdin_write(self, input):1153        if input:1154            try:1155                self.stdin.write(input)1156            except BrokenPipeError:1157                pass  # communicate() must ignore broken pipe errors.1158            except OSError as exc:1159                if exc.errno == errno.EINVAL:1160                    # bpo-19612, bpo-30418: On Windows, stdin.write() fails1161                    # with EINVAL if the child process exited or if the child1162                    # process is still running but closed the pipe.1163                    pass1164                else:1165                    raise1166 1167        try:1168            self.stdin.close()1169        except BrokenPipeError:1170            pass  # communicate() must ignore broken pipe errors.1171        except OSError as exc:1172            if exc.errno == errno.EINVAL:1173                pass1174            else:1175                raise1176 1177    def communicate(self, input=None, timeout=None):1178        """Interact with process: Send data to stdin and close it.1179        Read data from stdout and stderr, until end-of-file is1180        reached.  Wait for process to terminate.1181 1182        The optional "input" argument should be data to be sent to the1183        child process, or None, if no data should be sent to the child.1184        communicate() returns a tuple (stdout, stderr).1185 1186        By default, all communication is in bytes, and therefore any1187        "input" should be bytes, and the (stdout, stderr) will be bytes.1188        If in text mode (indicated by self.text_mode), any "input" should1189        be a string, and (stdout, stderr) will be strings decoded1190        according to locale encoding, or by "encoding" if set. Text mode1191        is triggered by setting any of text, encoding, errors or1192        universal_newlines.1193        """1194 1195        if self._communication_started and input:1196            raise ValueError("Cannot send input after starting communication")1197 1198        # Optimization: If we are not worried about timeouts, we haven't1199        # started communicating, and we have one or zero pipes, using select()1200        # or threads is unnecessary.

Showing the first 1,200 of 2258 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai