subprocess subprocesses with accessible io streams for more information about this module see pep 324 c 20032005 by peter astrand astrandlysator liu se licensed to psf under a contributor agreement import builtins import errno import io import locale import os import time import signal import sys import threading import warnings import contextlib from time import monotonic as time import types try import fcntl except importerror fcntl none all popen pipe stdout call checkcall getstatusoutput getoutput checkoutput run calledprocesserror devnull subprocesserror timeoutexpired completedprocess note we intentionally exclude list2cmdline as it is considered an internal implementation detail issue10838 use presence of msvcrt to detect windowslike platforms see bpo8110 try import msvcrt except modulenotfounderror mswindows false else mswindows true wasm32emscripten and wasm32wasi do not support processes canforkexec sys platform not in emscripten wasi if mswindows import winapi from winapi import createnewconsole createnewprocessgroup stdinputhandle stdoutputhandle stderrorhandle swhide startfusestdhandles startfuseshowwindow abovenormalpriorityclass belownormalpriorityclass highpriorityclass idlepriorityclass normalpriorityclass realtimepriorityclass createnowindow detachedprocess createdefaulterrormode createbreakawayfromjob all extendcreatenewconsole createnewprocessgroup stdinputhandle stdoutputhandle stderrorhandle swhide startfusestdhandles startfuseshowwindow startupinfo abovenormalpriorityclass belownormalpriorityclass highpriorityclass idlepriorityclass normalpriorityclass realtimepriorityclass createnowindow detachedprocess createdefaulterrormode createbreakawayfromjob else if canforkexec from posixsubprocess import forkexec as forkexec used in methods that are called by del waitpid os waitpid waitstatustoexitcode os waitstatustoexitcode wifstopped os wifstopped wstopsig os wstopsig wnohang os wnohang else forkexec none waitpid none waitstatustoexitcode none wifstopped none wstopsig none wnohang none import select import selectors exception classes used by this module class subprocesserrorexception pass class calledprocesserrorsubprocesserror def initself returncode cmd outputnone stderrnone self returncode returncode self cmd cmd self output output self stderr stderr def strself if self returncode and self returncode 0 try return command s died with r self cmd signal signalsself returncode except valueerror return command s died with unknown signal d self cmd self returncode else return command s returned nonzero exit status d self cmd self returncode property def stdoutself there s no obvious reason to set this but allow it anyway so stdout is a transparent alias for output this exception is raised when the timeout expires while waiting for a child process attributes cmd output stdout stderr timeout there s no obvious reason to set this but allow it anyway so stdout is a transparent alias for output when select or poll has indicated that the file is writable we can write up to pipebuf bytes without risk of blocking posix defines pipebuf as 512 pollselect have the advantage of not requiring any extra file descriptor contrarily to epollkqueue also they require a single syscall on windows we just need to close popen handle when we no longer need it so that the kernel can free it popen handle gets closed implicitly when the popen instance is finalized see handle del which is calling closehandle as requested in 1 so there is nothing for cleanup to do 1 https docs microsoft comenuswindowsdesktopprocthread creatingprocesses this lists holds popen instances for which the underlying process had not exited at the time its del method got called those processes are waited for synchronously from cleanup when a new popen object is created to avoid zombie processes this can happen if two threads create a new popen instance it s harmless that it was already removed so ignore xxx this function is only used by multiprocessing and the test suite but it s here so that it can be imported when python is compiled without threads return a list of commandline arguments reproducing the current optimization settings in sys flags args value sys flags optimize if value 0 args append o value return args def argsfrominterpreterflags inspect i interactive i o is handled in optimargsfrominterpreterflags w options x options return default text encoding and emit encodingwarning if sys flags warndefaultencoding is true run command with arguments wait for command to complete or timeout then return the returncode attribute the arguments are the same as for the popen constructor example retcode callls l we don t call p wait again as p exit does that for us run command with arguments wait for command to complete if the exit code was zero then return otherwise raise calledprocesserror the calledprocesserror object will have the return code in the returncode attribute the arguments are the same as for the call function example checkcallls l for kw in stdout check if kw in kwargs raise valueerrorf kw argument not allowed it will be overridden if input in kwargs and kwargs input is none explicitly passing inputnone was previously equivalent to passing an empty string that is maintained here for backwards compatibility if kwargs get universalnewlines or kwargs get text or kwargs get encoding or kwargs get errors empty else empty b kwargs input empty return runpopenargs stdoutpipe timeouttimeout checktrue kwargs stdout class completedprocessobject def initself args returncode stdoutnone stderrnone self args args self returncode returncode self stdout stdout self stderr stderr def reprself args args r formatself args returncode r formatself returncode if self stdout is not none args append stdout r formatself stdout if self stderr is not none args append stderr r formatself stderr return formattypeself name joinargs classgetitem classmethodtypes genericalias def checkreturncodeself run command with arguments and return a completedprocess instance the returned instance will have attributes args returncode stdout and stderr by default stdout and stderr are not captured and those attributes will be none pass stdoutpipe andor stderrpipe in order to capture them or pass captureoutputtrue to capture both if check is true and the exit code was nonzero it raises a calledprocesserror the calledprocesserror object will have the return code in the returncode attribute and output stderr attributes if those streams were captured if timeout is given and the process takes too long a timeoutexpired exception will be raised there is an optional argument input allowing you to pass bytes or a string to the subprocess s stdin if you use this argument you may not also use the popen constructor s stdin argument as it will be used internally by default all communication is in bytes and therefore any input should be bytes and the stdout and stderr will be bytes if in text mode any input should be a string and stdout and stderr will be strings decoded according to locale encoding or by encoding if set text mode is triggered by setting any of text encoding errors or universalnewlines the other arguments are the same as for the popen constructor windows accumulates the output in a single blocking read call run on child threads with the timeout being done in a join on those threads communicate after kill is required to collect that and add it to the exception posix communicate already populated the output so far into the timeoutexpired exception we don t call process wait as exit does that for us translate a sequence of arguments into a command line string using the same rules as the ms c runtime 1 arguments are delimited by white space which is either a space or a tab 2 a string surrounded by double quotation marks is interpreted as a single argument regardless of white space contained within a quoted string can be embedded in an argument 3 a double quotation mark preceded by a backslash is interpreted as a literal double quotation mark 4 backslashes are interpreted literally unless they immediately precede a double quotation mark 5 if backslashes immediately precede a double quotation mark every pair of backslashes is interpreted as a literal backslash if the number of backslashes is odd the last backslash escapes the next double quotation mark as described in rule 3 see http msdn microsoft comenuslibrary17w5ykft aspx or search http msdn microsoft com for parsing c commandline arguments add a space to separate this argument from the others don t know if we need to double yet double backslashes normal char add remaining backslashes if any various tools for executing commands and looking at their output and status return exitcode output of executing cmd in a shell execute the string cmd in a shell with checkoutput and return a 2tuple status output the locale encoding is used to decode the output and process newlines a trailing newline is stripped from the output the exit status for the command can be interpreted according to the rules for the function wait example import subprocess subprocess getstatusoutput ls binls 0 binls subprocess getstatusoutput cat binjunk 1 cat binjunk no such file or directory subprocess getstatusoutput binjunk 127 sh binjunk not found subprocess getstatusoutput binkill 15 return output stdout or stderr of executing cmd in a shell like getstatusoutput except the exit status is ignored and the return value is a string containing the command s output example import subprocess subprocess getoutput ls binls binls check if posixspawn can be used for subprocess subprocess requires a posixspawn implementation that properly reports errors to the parent process sets errno on the following failures process attribute actions failed file actions failed exec failed prefer an implementation which can use vfork in some cases for best performance os posixspawn is not available posixspawn is a syscall on both macos and solaris and properly reports errors check libc name and runtime libc version parse glibc 2 28 as glibc 2 28 reject unknown format glibc 2 24 has a new linux posixspawn implementation using vfork which properly reports errors to the parent process note don t use the implementation in earlier glibc because it doesn t use vfork even if glibc 2 26 added a pipe to properly report errors to the parent process os confstr or csgnulibcversion value not available by default assume that posixspawn does not properly report errors these are primarily failsafe knobs for negatives a true value does not guarantee the given libcsyscall api will be used execute a child program in a new process for a complete description of the arguments see the python documentation arguments args a string or a sequence of program arguments bufsize supplied as the buffering argument to the open function when creating the stdinstdoutstderr pipe file objects executable a replacement program to execute stdin stdout and stderr these specify the executed programs standard input standard output and standard error file handles respectively preexecfn posix only an object to be called in the child process just before the child is executed closefds controls closing or inheriting of file descriptors shell if true the command will be executed through the shell cwd sets the current directory before the child is executed env defines the environment variables for the new process text if true decode stdin stdout and stderr using the given encoding if set or the system default otherwise universalnewlines alias of text provided for backwards compatibility startupinfo and creationflags windows only restoresignals posix only startnewsession posix only processgroup posix only group posix only extragroups posix only user posix only umask posix only passfds posix only encoding and errors text mode encoding and error handling to use for file objects stdin stdout and stderr attributes stdin stdout stderr pid returncode create new popen instance if not canforkexec raise oserror errno enotsup fsys platform does not support processes cleanup held while anything is calling waitpid before returncode has been updated to prevent clobbering returncode if wait or poll are called from multiple threads at once after acquiring the lock code must recheck self returncode to see if another thread just finished a waitpid call self waitpidlock threading lock self input none self communicationstarted false if bufsize is none bufsize 1 restore default if not isinstancebufsize int raise typeerrorbufsize must be an integer if pipesize is none pipesize 1 restore default if not isinstancepipesize int raise typeerrorpipesize must be an integer if mswindows if preexecfn is not none raise valueerrorpreexecfn is not supported on windows platforms else posix if passfds and not closefds warnings warnpassfds overriding closefds runtimewarning closefds true if startupinfo is not none raise valueerrorstartupinfo is only supported on windows platforms if creationflags 0 raise valueerrorcreationflags is only supported on windows platforms self args args self stdin none self stdout none self stderr none self pid none self returncode none self encoding encoding self errors errors self pipesize pipesize validate the combinations of text and universalnewlines if text is not none and universalnewlines is not none and booluniversalnewlines booltext raise subprocesserror cannot disambiguate when both text and universalnewlines are supplied but different pass one or the other self textmode encoding or errors or text or universalnewlines if self textmode and encoding is none self encoding encoding textencoding how long to resume waiting on a child after the first c there is no right value for this the purpose is to be polite yet remain good for interactive users trying to exit a tool self sigintwaitsecs 0 25 1xkcd221 getrandomnumber self closedchildpipefds false if self textmode if bufsize 1 linebuffering true use the default buffer size for the underlying binary streams since they don t support line buffering bufsize 1 else linebuffering false if processgroup is none processgroup 1 the internal apis are intonly gid none if group is not none if not hasattros setregid raise valueerrorthe group parameter is not supported on the current platform elif isinstancegroup str try import grp except importerror raise valueerrorthe group parameter cannot be a string on systems without the grp module gid grp getgrnamgroup grgid elif isinstancegroup int gid group else raise typeerrorgroup must be a string or an integer not formattypegroup if gid 0 raise valueerrorfgroup id cannot be negative got gid gids none if extragroups is not none if not hasattros setgroups raise valueerrorthe extragroups parameter is not supported on the current platform elif isinstanceextragroups str raise valueerrorgroups must be a list not a string gids for extragroup in extragroups if isinstanceextragroup str try import grp except importerror raise valueerroritems in extragroups cannot be strings on systems without the grp module gids appendgrp getgrnamextragroup grgid elif isinstanceextragroup int gids appendextragroup else raise typeerroritems in extragroups must be a string or integer not formattypeextragroup make sure that the gids are all positive here so we can do less checking in the c code for gidcheck in gids if gidcheck 0 raise valueerrorfgroup id cannot be negative got gidcheck uid none if user is not none if not hasattros setreuid raise valueerrorthe user parameter is not supported on the current platform elif isinstanceuser str try import pwd except importerror raise valueerrorthe user parameter cannot be a string on systems without the pwd module uid pwd getpwnamuser pwuid elif isinstanceuser int uid user else raise typeerroruser must be a string or an integer if uid 0 raise valueerrorfuser id cannot be negative got uid input and output objects the general principle is like this parent child p2cwrite stdin p2cread c2pread stdout c2pwrite errread stderr errwrite on posix the child objects are file descriptors on windows these are windows file handles the parent objects are file descriptors on both platforms the parent objects are 1 when not using pipes the child objects are 1 when not redirecting p2cread p2cwrite c2pread c2pwrite errread errwrite self gethandlesstdin stdout stderr from here on raising exceptions may cause file descriptor leakage we wrap os handles before launching the child otherwise a quickly terminating child could make our fds unwrappable see 8458 if mswindows if p2cwrite 1 p2cwrite msvcrt openosfhandlep2cwrite detach 0 if c2pread 1 c2pread msvcrt openosfhandlec2pread detach 0 if errread 1 errread msvcrt openosfhandleerrread detach 0 try if p2cwrite 1 self stdin io openp2cwrite wb bufsize if self textmode self stdin io textiowrapperself stdin writethroughtrue linebufferinglinebuffering encodingencoding errorserrors if c2pread 1 self stdout io openc2pread rb bufsize if self textmode self stdout io textiowrapperself stdout encodingencoding errorserrors if errread 1 self stderr io openerrread rb bufsize if self textmode self stderr io textiowrapperself stderr encodingencoding errorserrors self executechildargs executable preexecfn closefds passfds cwd env startupinfo creationflags shell p2cread p2cwrite c2pread c2pwrite errread errwrite restoresignals gid gids uid umask startnewsession processgroup except cleanup if the child failed starting for f in filternone self stdin self stdout self stderr try f close except oserror pass ignore ebadf or other errors if not self closedchildpipefds toclose if stdin pipe toclose appendp2cread if stdout pipe toclose appendc2pwrite if stderr pipe toclose appenderrwrite if hasattrself devnull toclose appendself devnull for fd in toclose try if mswindows and isinstancefd handle fd close else os closefd except oserror pass raise def reprself objrepr fself class name freturncode self returncode args self args r if lenobjrepr 80 objrepr objrepr 76 return objrepr classgetitem classmethodtypes genericalias property def universalnewlinesself universalnewlines as retained as an alias of textmode for api compatibility bpo31756 return self textmode universalnewlines setter def universalnewlinesself universalnewlines self textmode booluniversalnewlines def translatenewlinesself data encoding errors data data decodeencoding errors return data replacern n replacer n def enterself return self def exitself exctype value traceback if self stdout self stdout close if self stderr self stderr close try flushing a bufferedwriter may raise an error if self stdin self stdin close finally if exctype keyboardinterrupt https bugs python orgissue25942 in the case of a keyboardinterrupt we assume the sigint was also already sent to our child processes we can t block indefinitely as that is not user friendly if we have not already waited a brief amount of time in an interrupted wait or communicate call do so here for consistency if self sigintwaitsecs 0 try self waittimeoutself sigintwaitsecs except timeoutexpired pass self sigintwaitsecs 0 note that this has been done return resume the keyboardinterrupt wait for the process to terminate to avoid zombies self wait def delself maxsizesys maxsize warnwarnings warn if not self childcreated we didn t get to successfully create a child process return if self returncode is none not reading subprocess exit status creates a zombie process which is only destroyed at the parent python process exit warnsubprocess s is still running self pid resourcewarning sourceself in case the child hasn t been waited on check if it s done self internalpolldeadstatemaxsize if self returncode is none and active is not none child is still running keep us alive until we can wait on it active appendself def getdevnullself if not hasattrself devnull self devnull os openos devnull os ordwr return self devnull def stdinwriteself input if input try self stdin writeinput except brokenpipeerror pass communicate must ignore broken pipe errors except oserror as exc if exc errno errno einval bpo19612 bpo30418 on windows stdin write fails with einval if the child process exited or if the child process is still running but closed the pipe pass else raise try self stdin close except brokenpipeerror pass communicate must ignore broken pipe errors except oserror as exc if exc errno errno einval pass else raise def communicateself inputnone timeoutnone if self communicationstarted and input raise valueerrorcannot send input after starting communication optimization if we are not worried about timeouts we haven t started communicating and we have one or zero pipes using select or threads is unnecessary if timeout is none and not self communicationstarted and self stdin self stdout self stderr countnone 2 stdout none stderr none if self stdin self stdinwriteinput elif self stdout stdout self stdout read self stdout close elif self stderr stderr self stderr read self stderr close self wait else if timeout is not none endtime time timeout else endtime none try stdout stderr self communicateinput endtime timeout except keyboardinterrupt https bugs python orgissue25942 see the detailed comment in wait if timeout is not none siginttimeout minself sigintwaitsecs self remainingtimeendtime else siginttimeout self sigintwaitsecs self sigintwaitsecs 0 nothing else should wait try self waittimeoutsiginttimeout except timeoutexpired pass raise resume the keyboardinterrupt finally self communicationstarted true sts self waittimeoutself remainingtimeendtime return stdout stderr def pollself convenience for communicate when computing timeouts if endtime is none return none else return endtime time def checktimeoutself endtime origtimeout stdoutseq stderrseq skipcheckandraisefalse wait for child process to terminate returns self returncode if timeout is not none endtime time timeout try return self waittimeouttimeout except keyboardinterrupt https bugs python orgissue25942 the first keyboard interrupt waits briefly for the child to exit under the common assumption that it also received the c generated sigint and will exit rapidly if timeout is not none siginttimeout minself sigintwaitsecs self remainingtimeendtime else siginttimeout self sigintwaitsecs self sigintwaitsecs 0 nothing else should wait try self waittimeoutsiginttimeout except timeoutexpired pass raise resume the keyboardinterrupt def closepipefdsself p2cread p2cwrite c2pread c2pwrite errread errwrite self devnull is not always defined devnullfd getattrself devnull none with contextlib exitstack as stack if mswindows if p2cread 1 stack callbackp2cread close if c2pwrite 1 stack callbackc2pwrite close if errwrite 1 stack callbackerrwrite close else if p2cread 1 and p2cwrite 1 and p2cread devnullfd stack callbackos close p2cread if c2pwrite 1 and c2pread 1 and c2pwrite devnullfd stack callbackos close c2pwrite if errwrite 1 and errread 1 and errwrite devnullfd stack callbackos close errwrite if devnullfd is not none stack callbackos close devnullfd prevent a double close of these handlesfds from init on error self closedchildpipefds true contextlib contextmanager def onerrorfdcloserself windows methods construct and return tuple with io objects p2cread p2cwrite c2pread c2pwrite errread errwrite assuming filelike object assuming filelike object assuming filelike object return a duplicate of handle which is inheritable h winapi duplicatehandle winapi getcurrentprocess handle winapi getcurrentprocess 0 1 winapi duplicatesameaccess return handleh def filterhandlelistself handlelist an handle with it s lowest two bits set might be a special console handle that if passed in lpattributelisthandlelist will cause it to fail execute program ms windows version assert not passfds passfds not supported on windows if isinstanceargs str pass elif isinstanceargs bytes if shell raise typeerror bytes args is not allowed on windows args list2cmdlineargs elif isinstanceargs os pathlike if shell raise typeerror pathlike args is not allowed when shell is true args list2cmdlineargs else args list2cmdlineargs if executable is not none executable os fsdecodeexecutable process startup details if startupinfo is none startupinfo startupinfo else bpo34044 copy startupinfo since it is modified above so the caller can reuse it multiple times startupinfo startupinfo copy usestdhandles 1 not in p2cread c2pwrite errwrite if usestdhandles startupinfo dwflags winapi startfusestdhandles startupinfo hstdinput p2cread startupinfo hstdoutput c2pwrite startupinfo hstderror errwrite attributelist startupinfo lpattributelist havehandlelist boolattributelist and handlelist in attributelist and attributelisthandlelist if we were given an handlelist or need to create one if havehandlelist or usestdhandles and closefds if attributelist is none attributelist startupinfo lpattributelist handlelist attributelisthandlelist listattributelist gethandlelist if usestdhandles handlelist intp2cread intc2pwrite interrwrite handlelist self filterhandlelisthandlelist if handlelist if not closefds warnings warnstartupinfo lpattributelist handlelist overriding closefds runtimewarning when using the handlelist we always request to inherit handles but the only handles that will be inherited are the ones in the handlelist closefds false if shell startupinfo dwflags winapi startfuseshowwindow startupinfo wshowwindow winapi swhide if not executable gh101283 without a fullyqualified path before windows checks the system directories it first looks in the application directory and also the current directory if needcurrentdirectoryforexepathwexename is true so try to avoid executing unqualified cmd exe comspec os environ get comspec if not comspec systemroot os environ get systemroot comspec os path joinsystemroot system32 cmd exe if not os path isabscomspec raise filenotfounderror shell not found neither comspec nor systemroot is set if os path isabscomspec executable comspec else comspec executable args c format comspec args if cwd is not none cwd os fsdecodecwd sys auditsubprocess popen executable args cwd env start the process try hp ht pid tid winapi createprocessexecutable args no special security none none intnot closefds creationflags env cwd startupinfo finally child is launched close the parent s copy of those pipe handles that only the child should have open you need to make sure that no handles to the write end of the output pipe are maintained in this process or else the pipe will not close when the child process exits and the readfile will hang self closepipefdsp2cread p2cwrite c2pread c2pwrite errread errwrite retain the process handle but close the thread handle self childcreated true self handle handlehp self pid pid winapi closehandleht def internalpollself deadstatenone waitforsingleobjectwinapi waitforsingleobject waitobject0winapi waitobject0 getexitcodeprocesswinapi getexitcodeprocess if self returncode is none if waitforsingleobjectself handle 0 waitobject0 self returncode getexitcodeprocessself handle return self returncode def waitself timeout api note returns immediately if timeoutmillis 0 start reader threads feeding into a list hanging off of this object unless they ve already been started wait for the reader threads or time out if we time out the threads remain reading and the fds left open in case the user calls communicate again collect the output from and close both pipes now that we know both have been read successfully all data exchanged translate lists into strings send a signal to the process don t signal a process that we know has already died if self returncode is not none return if sig signal sigterm self terminate elif sig signal ctrlcevent os killself pid signal ctrlcevent elif sig signal ctrlbreakevent os killself pid signal ctrlbreakevent else raise valueerrorunsupported signal formatsig def terminateself don t terminate a process that we know has already died erroraccessdenied winerror 5 is received when the process already died posix methods construct and return tuple with io objects p2cread p2cwrite c2pread c2pwrite errread errwrite assuming filelike object assuming filelike object assuming filelike object execute program using os posixspawn if env is none env os environ kwargs if restoresignals see pyrestoresignals in pythonpylifecycle c sigset for signame in sigpipe sigxfz sigxfsz signum getattrsignal signame none if signum is not none sigset appendsignum kwargs setsigdef sigset fileactions for fd in p2cwrite c2pread errread if fd 1 fileactions appendos posixspawnclose fd for fd fd2 in p2cread 0 c2pwrite 1 errwrite 2 if fd 1 fileactions appendos posixspawndup2 fd fd2 if fileactions kwargs fileactions fileactions self pid os posixspawnexecutable args env kwargs self childcreated true self closepipefdsp2cread p2cwrite c2pread c2pwrite errread errwrite def executechildself args executable preexecfn closefds passfds cwd env startupinfo creationflags shell p2cread p2cwrite c2pread c2pwrite errread errwrite restoresignals gid gids uid umask startnewsession processgroup on android the default shell is at systembinsh for transferring possible exec failure from child to parent data format exception name hex errno description pickle is not used it is complex and involves memory allocation errpipewrite must not be in the standard io 0 1 or 2 fd range we must avoid complex work that could involve malloc or free in the child process to avoid potential deadlocks thus we do all this here and pass it to forkexec this matches the behavior of os execvpe be sure the fd is closed no matter what wait for exec to fail or succeed possibly raising an exception limited in size be sure the fd is closed no matter what the encoding here should match the encoding written in by the subprocess implementations like posixsubprocess the error must be from chdircwd all callers to this function must hold self waitpidlock this method is called indirectly by del so it cannot refer to anything outside of its local scope if wifstoppedsts self returncode wstopsigsts else self returncode waitstatustoexitcodests def internalpollself deadstatenone waitpidwaitpid wnohangwnohang echilderrno echild if self returncode is none if not self waitpidlock acquirefalse something else is busy calling waitpid don t allow two at once we know nothing yet return none try if self returncode is not none return self returncode another thread waited pid sts waitpidself pid wnohang if pid self pid self handleexitstatussts except oserror as e if deadstate is not none self returncode deadstate elif e errno echild this happens if sigcld is set to be ignored or waiting for child processes has otherwise been disabled for our process this child is dead we can t get the status http bugs python orgissue15756 self returncode 0 finally self waitpidlock release return self returncode def trywaitself waitflags this happens if sigcld is set to be ignored or waiting for child processes has otherwise been disabled for our process this child is dead we can t get the status internal implementation of wait on posix if self returncode is not none return self returncode if timeout is not none endtime time timeout enter a busy loop if we have a timeout this busy loop was cribbed from libthreading py in thread wait at r71065 delay 0 0005 500 us initial delay of 1 ms while true if self waitpidlock acquirefalse try if self returncode is not none break another thread waited pid sts self trywaitos wnohang assert pid self pid or pid 0 if pid self pid self handleexitstatussts break finally self waitpidlock release remaining self remainingtimeendtime if remaining 0 raise timeoutexpiredself args timeout delay mindelay 2 remaining 05 time sleepdelay else while self returncode is none with self waitpidlock if self returncode is not none break another thread waited pid sts self trywait0 check the pid and loop as waitpid has been known to return 0 even without wnohang in odd situations http bugs python orgissue14396 if pid self pid self handleexitstatussts return self returncode def communicateself input endtime origtimeout if self stdin and not self communicationstarted flush stdio buffer this might block if the user has been writing to stdin in an uncontrolled fashion try self stdin flush except brokenpipeerror pass communicate must ignore brokenpipeerror if not input try self stdin close except brokenpipeerror pass communicate must ignore brokenpipeerror stdout none stderr none only create this mapping if we haven t already if not self communicationstarted self fileobj2output if self stdout self fileobj2outputself stdout if self stderr self fileobj2outputself stderr if self stdout stdout self fileobj2outputself stdout if self stderr stderr self fileobj2outputself stderr self saveinputinput if self input inputview memoryviewself input with popenselector as selector if self stdin and input selector registerself stdin selectors eventwrite if self stdout and not self stdout closed selector registerself stdout selectors eventread if self stderr and not self stderr closed selector registerself stderr selectors eventread while selector getmap timeout self remainingtimeendtime if timeout is not none and timeout 0 self checktimeoutendtime origtimeout stdout stderr skipcheckandraisetrue raise runtimeerror impossible checktimeout skipcheckandraisetrue failed to raise timeoutexpired ready selector selecttimeout self checktimeoutendtime origtimeout stdout stderr xxx rewrite these to use nonblocking io on the file objects they are no longer using c stdio for key events in ready if key fileobj is self stdin chunk inputviewself inputoffset self inputoffset pipebuf try self inputoffset os writekey fd chunk except brokenpipeerror selector unregisterkey fileobj key fileobj close else if self inputoffset lenself input selector unregisterkey fileobj key fileobj close elif key fileobj in self stdout self stderr data os readkey fd 32768 if not data selector unregisterkey fileobj key fileobj close self fileobj2outputkey fileobj appenddata self waittimeoutself remainingtimeendtime all data exchanged translate lists into strings if stdout is not none stdout b joinstdout if stderr is not none stderr b joinstderr translate newlines if requested this also turns bytes into strings if self textmode if stdout is not none stdout self translatenewlinesstdout self stdout encoding self stdout errors if stderr is not none stderr self translatenewlinesstderr self stderr encoding self stderr errors return stdout stderr def saveinputself input this method is called from the communicatewith methods so that if we time out while communicating we can continue sending input if we retry if self stdin and self input is none self inputoffset 0 self input input if input is not none and self textmode self input self input encodeself stdin encoding self stdin errors def sendsignalself sig bpo38630 polling reduces the risk of sending a signal to the wrong process if the process completed the popen returncode attribute is still none and the pid has been reassigned recycled to a new different process this race condition can happens in two cases case 1 thread a calls popen poll thread b calls popen sendsignal in thread a waitpid succeed and returns the exit status thread b calls kill because poll in thread a did not set returncode yet calling poll in thread b prevents the race condition thanks to popen waitpidlock case 2 waitpidpid 0 has been called directly without using popen methods returncode is still none is this case calling popen poll will set returncode to a default value since waitpid fails with processlookuperror skip signalling a process that we know has already died the race condition can still happen if the race condition described above happens between the returncode test and the kill call suppress the race condition error bpo40550 terminate the process with sigterm kill the process with sigkill subprocess subprocesses with accessible i o streams for more information about this module see pep 324 c 2003 2005 by peter astrand astrand lysator liu se licensed to psf under a contributor agreement subprocesses with accessible i o streams this module allows you to spawn processes connect to their input output error pipes and obtain their return codes for a complete description of this module see the python documentation main api run runs a command waits for it to complete then returns a completedprocess instance popen a class for flexibly executing a command in a new process constants devnull special value that indicates that os devnull should be used pipe special value that indicates a pipe should be created stdout special value that indicates that stderr should go to stdout older api call runs a command waits for it to complete then returns the return code check_call same as call but raises calledprocesserror if return code is not 0 check_output same as check_call but returns the contents of stdout instead of a return code getoutput runs a command in the shell waits for it to complete then returns the output getstatusoutput runs a command in the shell waits for it to complete then returns a exitcode output tuple note we intentionally exclude list2cmdline as it is considered an internal implementation detail issue10838 use presence of msvcrt to detect windows like platforms see bpo 8110 wasm32 emscripten and wasm32 wasi do not support processes used in methods that are called by __del__ exception classes used by this module raised when run is called with check true and the process returns a non zero exit status attributes cmd returncode stdout stderr output alias for output attribute to match stderr there s no obvious reason to set this but allow it anyway so stdout is a transparent alias for output this exception is raised when the timeout expires while waiting for a child process attributes cmd output stdout stderr timeout there s no obvious reason to set this but allow it anyway so stdout is a transparent alias for output when select or poll has indicated that the file is writable we can write up to _pipe_buf bytes without risk of blocking posix defines pipe_buf as 512 poll select have the advantage of not requiring any extra file descriptor contrarily to epoll kqueue also they require a single syscall on windows we just need to close popen _handle when we no longer need it so that the kernel can free it popen _handle gets closed implicitly when the popen instance is finalized see handle __del__ which is calling closehandle as requested in 1 so there is nothing for _cleanup to do 1 https docs microsoft com en us windows desktop procthread creating processes this lists holds popen instances for which the underlying process had not exited at the time its __del__ method got called those processes are wait ed for synchronously from _cleanup when a new popen object is created to avoid zombie processes this can happen if two threads create a new popen instance it s harmless that it was already removed so ignore xxx this function is only used by multiprocessing and the test suite but it s here so that it can be imported when python is compiled without threads return a list of command line arguments reproducing the current optimization settings in sys flags return a list of command line arguments reproducing the current settings in sys flags sys warnoptions and sys _xoptions inspect i interactive i o is handled in _optim_args_from_interpreter_flags w options x options return default text encoding and emit encodingwarning if sys flags warn_default_encoding is true run command with arguments wait for command to complete or timeout then return the returncode attribute the arguments are the same as for the popen constructor example retcode call ls l including keyboardinterrupt wait handled that we don t call p wait again as p __exit__ does that for us run command with arguments wait for command to complete if the exit code was zero then return otherwise raise calledprocesserror the calledprocesserror object will have the return code in the returncode attribute the arguments are the same as for the call function example check_call ls l run command with arguments and return its output if the exit code was non zero it raises a calledprocesserror the calledprocesserror object will have the return code in the returncode attribute and output in the output attribute the arguments are the same as for the popen constructor example check_output ls l dev null b crw rw rw 1 root root 1 3 oct 18 2007 dev null n the stdout argument is not allowed as it is used internally to capture standard error in the result use stderr stdout check_output bin sh c ls l non_existent_file exit 0 stderr stdout b ls non_existent_file no such file or directory n there is an additional optional argument input allowing you to pass a string to the subprocess s stdin if you use this argument you may not also use the popen constructor s stdin argument as it too will be used internally example check_output sed e s foo bar input b when in the course of fooman events n b when in the course of barman events n by default all communication is in bytes and therefore any input should be bytes and the return value will be bytes if in text mode any input should be a string and the return value will be a string decoded according to locale encoding or by encoding if set text mode is triggered by setting any of text encoding errors or universal_newlines explicitly passing input none was previously equivalent to passing an empty string that is maintained here for backwards compatibility a process that has finished running this is returned by run attributes args the list or str args passed to run returncode the exit code of the process negative for signals stdout the standard output none if not captured stderr the standard error none if not captured raise calledprocesserror if the exit code is non zero run command with arguments and return a completedprocess instance the returned instance will have attributes args returncode stdout and stderr by default stdout and stderr are not captured and those attributes will be none pass stdout pipe and or stderr pipe in order to capture them or pass capture_output true to capture both if check is true and the exit code was non zero it raises a calledprocesserror the calledprocesserror object will have the return code in the returncode attribute and output stderr attributes if those streams were captured if timeout is given and the process takes too long a timeoutexpired exception will be raised there is an optional argument input allowing you to pass bytes or a string to the subprocess s stdin if you use this argument you may not also use the popen constructor s stdin argument as it will be used internally by default all communication is in bytes and therefore any input should be bytes and the stdout and stderr will be bytes if in text mode any input should be a string and stdout and stderr will be strings decoded according to locale encoding or by encoding if set text mode is triggered by setting any of text encoding errors or universal_newlines the other arguments are the same as for the popen constructor windows accumulates the output in a single blocking read call run on child threads with the timeout being done in a join on those threads communicate _after_ kill is required to collect that and add it to the exception posix _communicate already populated the output so far into the timeoutexpired exception including keyboardinterrupt communicate handled that we don t call process wait as __exit__ does that for us translate a sequence of arguments into a command line string using the same rules as the ms c runtime 1 arguments are delimited by white space which is either a space or a tab 2 a string surrounded by double quotation marks is interpreted as a single argument regardless of white space contained within a quoted string can be embedded in an argument 3 a double quotation mark preceded by a backslash is interpreted as a literal double quotation mark 4 backslashes are interpreted literally unless they immediately precede a double quotation mark 5 if backslashes immediately precede a double quotation mark every pair of backslashes is interpreted as a literal backslash if the number of backslashes is odd the last backslash escapes the next double quotation mark as described in rule 3 see http msdn microsoft com en us library 17w5ykft aspx or search http msdn microsoft com for parsing c command line arguments add a space to separate this argument from the others don t know if we need to double yet double backslashes normal char add remaining backslashes if any various tools for executing commands and looking at their output and status return exitcode output of executing cmd in a shell execute the string cmd in a shell with check_output and return a 2 tuple status output the locale encoding is used to decode the output and process newlines a trailing newline is stripped from the output the exit status for the command can be interpreted according to the rules for the function wait example import subprocess subprocess getstatusoutput ls bin ls 0 bin ls subprocess getstatusoutput cat bin junk 1 cat bin junk no such file or directory subprocess getstatusoutput bin junk 127 sh bin junk not found subprocess getstatusoutput bin kill 15 return output stdout or stderr of executing cmd in a shell like getstatusoutput except the exit status is ignored and the return value is a string containing the command s output example import subprocess subprocess getoutput ls bin ls bin ls check if posix_spawn can be used for subprocess subprocess requires a posix_spawn implementation that properly reports errors to the parent process sets errno on the following failures process attribute actions failed file actions failed exec failed prefer an implementation which can use vfork in some cases for best performance os posix_spawn is not available posix_spawn is a syscall on both macos and solaris and properly reports errors check libc name and runtime libc version parse glibc 2 28 as glibc 2 28 reject unknown format glibc 2 24 has a new linux posix_spawn implementation using vfork which properly reports errors to the parent process note don t use the implementation in earlier glibc because it doesn t use vfork even if glibc 2 26 added a pipe to properly report errors to the parent process os confstr or cs_gnu_libc_version value not available by default assume that posix_spawn does not properly report errors these are primarily fail safe knobs for negatives a true value does not guarantee the given libc syscall api will be used execute a child program in a new process for a complete description of the arguments see the python documentation arguments args a string or a sequence of program arguments bufsize supplied as the buffering argument to the open function when creating the stdin stdout stderr pipe file objects executable a replacement program to execute stdin stdout and stderr these specify the executed programs standard input standard output and standard error file handles respectively preexec_fn posix only an object to be called in the child process just before the child is executed close_fds controls closing or inheriting of file descriptors shell if true the command will be executed through the shell cwd sets the current directory before the child is executed env defines the environment variables for the new process text if true decode stdin stdout and stderr using the given encoding if set or the system default otherwise universal_newlines alias of text provided for backwards compatibility startupinfo and creationflags windows only restore_signals posix only start_new_session posix only process_group posix only group posix only extra_groups posix only user posix only umask posix only pass_fds posix only encoding and errors text mode encoding and error handling to use for file objects stdin stdout and stderr attributes stdin stdout stderr pid returncode set here since __del__ checks it create new popen instance held while anything is calling waitpid before returncode has been updated to prevent clobbering returncode if wait or poll are called from multiple threads at once after acquiring the lock code must re check self returncode to see if another thread just finished a waitpid call restore default restore default posix validate the combinations of text and universal_newlines how long to resume waiting on a child after the first c there is no right value for this the purpose is to be polite yet remain good for interactive users trying to exit a tool 1 xkcd221 getrandomnumber use the default buffer size for the underlying binary streams since they don t support line buffering the internal apis are int only make sure that the gids are all positive here so we can do less checking in the c code input and output objects the general principle is like this parent child p2cwrite stdin p2cread c2pread stdout c2pwrite errread stderr errwrite on posix the child objects are file descriptors on windows these are windows file handles the parent objects are file descriptors on both platforms the parent objects are 1 when not using pipes the child objects are 1 when not redirecting from here on raising exceptions may cause file descriptor leakage we wrap os handles before launching the child otherwise a quickly terminating child could make our fds unwrappable see 8458 cleanup if the child failed starting ignore ebadf or other errors universal_newlines as retained as an alias of text_mode for api compatibility bpo 31756 flushing a bufferedwriter may raise an error https bugs python org issue25942 in the case of a keyboardinterrupt we assume the sigint was also already sent to our child processes we can t block indefinitely as that is not user friendly if we have not already waited a brief amount of time in an interrupted wait or communicate call do so here for consistency note that this has been done resume the keyboardinterrupt wait for the process to terminate to avoid zombies we didn t get to successfully create a child process not reading subprocess exit status creates a zombie process which is only destroyed at the parent python process exit in case the child hasn t been waited on check if it s done child is still running keep us alive until we can wait on it communicate must ignore broken pipe errors bpo 19612 bpo 30418 on windows stdin write fails with einval if the child process exited or if the child process is still running but closed the pipe communicate must ignore broken pipe errors interact with process send data to stdin and close it read data from stdout and stderr until end of file is reached wait for process to terminate the optional input argument should be data to be sent to the child process or none if no data should be sent to the child communicate returns a tuple stdout stderr by default all communication is in bytes and therefore any input should be bytes and the stdout stderr will be bytes if in text mode indicated by self text_mode any input should be a string and stdout stderr will be strings decoded according to locale encoding or by encoding if set text mode is triggered by setting any of text encoding errors or universal_newlines optimization if we are not worried about timeouts we haven t started communicating and we have one or zero pipes using select or threads is unnecessary https bugs python org issue25942 see the detailed comment in wait nothing else should wait resume the keyboardinterrupt check if child process has terminated set and return returncode attribute convenience for _communicate when computing timeouts convenience for checking if a timeout has expired wait for child process to terminate returns self returncode https bugs python org issue25942 the first keyboard interrupt waits briefly for the child to exit under the common assumption that it also received the c generated sigint and will exit rapidly nothing else should wait resume the keyboardinterrupt self _devnull is not always defined prevent a double close of these handles fds from __init__ on error helper to ensure file descriptors opened in _get_handles are closed windows methods construct and return tuple with io objects p2cread p2cwrite c2pread c2pwrite errread errwrite assuming file like object assuming file like object assuming file like object return a duplicate of handle which is inheritable filter out console handles that can t be used in lpattributelist handle_list and make sure the list isn t empty this also removes duplicate handles an handle with it s lowest two bits set might be a special console handle that if passed in lpattributelist handle_list will cause it to fail execute program ms windows version process startup details bpo 34044 copy startupinfo since it is modified above so the caller can reuse it multiple times if we were given an handle_list or need to create one when using the handle_list we always request to inherit handles but the only handles that will be inherited are the ones in the handle_list gh 101283 without a fully qualified path before windows checks the system directories it first looks in the application directory and also the current directory if needcurrentdirectoryforexepathw exename is true so try to avoid executing unqualified cmd exe start the process no special security child is launched close the parent s copy of those pipe handles that only the child should have open you need to make sure that no handles to the write end of the output pipe are maintained in this process or else the pipe will not close when the child process exits and the readfile will hang retain the process handle but close the thread handle check if child process has terminated returns returncode attribute this method is called by __del__ so it can only refer to objects in its local scope internal implementation of wait on windows api note returns immediately if timeout_millis 0 start reader threads feeding into a list hanging off of this object unless they ve already been started wait for the reader threads or time out if we time out the threads remain reading and the fds left open in case the user calls communicate again collect the output from and close both pipes now that we know both have been read successfully all data exchanged translate lists into strings send a signal to the process don t signal a process that we know has already died terminates the process don t terminate a process that we know has already died error_access_denied winerror 5 is received when the process already died posix methods construct and return tuple with io objects p2cread p2cwrite c2pread c2pwrite errread errwrite assuming file like object assuming file like object child s stdout is not set use parent s stdout assuming file like object execute program using os posix_spawn see _py_restoresignals in python pylifecycle c execute program posix version on android the default shell is at system bin sh for transferring possible exec failure from child to parent data format exception name hex errno description pickle is not used it is complex and involves memory allocation errpipe_write must not be in the standard io 0 1 or 2 fd range we must avoid complex work that could involve malloc or free in the child process to avoid potential deadlocks thus we do all this here and pass it to fork_exec use execv instead of execve this matches the behavior of os _execvpe be sure the fd is closed no matter what wait for exec to fail or succeed possibly raising an exception limited in size be sure the fd is closed no matter what the encoding here should match the encoding written in by the subprocess implementations like _posixsubprocess the error must be from chdir cwd all callers to this function must hold self _waitpid_lock this method is called indirectly by __del__ so it cannot refer to anything outside of its local scope check if child process has terminated returns returncode attribute this method is called by __del__ so it cannot reference anything outside of the local scope nor can any methods it calls something else is busy calling waitpid don t allow two at once we know nothing yet another thread waited this happens if sigcld is set to be ignored or waiting for child processes has otherwise been disabled for our process this child is dead we can t get the status http bugs python org issue15756 all callers to this function must hold self _waitpid_lock this happens if sigcld is set to be ignored or waiting for child processes has otherwise been disabled for our process this child is dead we can t get the status internal implementation of wait on posix enter a busy loop if we have a timeout this busy loop was cribbed from lib threading py in thread wait at r71065 500 us initial delay of 1 ms another thread waited another thread waited check the pid and loop as waitpid has been known to return 0 even without wnohang in odd situations http bugs python org issue14396 flush stdio buffer this might block if the user has been writing to stdin in an uncontrolled fashion communicate must ignore brokenpipeerror communicate must ignore brokenpipeerror only create this mapping if we haven t already impossible xxx rewrite these to use non blocking i o on the file objects they are no longer using c stdio all data exchanged translate lists into strings translate newlines if requested this also turns bytes into strings this method is called from the _communicate_with_ methods so that if we time out while communicating we can continue sending input if we retry send a signal to the process bpo 38630 polling reduces the risk of sending a signal to the wrong process if the process completed the popen returncode attribute is still none and the pid has been reassigned recycled to a new different process this race condition can happens in two cases case 1 thread a calls popen poll thread b calls popen send_signal in thread a waitpid succeed and returns the exit status thread b calls kill because poll in thread a did not set returncode yet calling poll in thread b prevents the race condition thanks to popen _waitpid_lock case 2 waitpid pid 0 has been called directly without using popen methods returncode is still none is this case calling popen poll will set returncode to a default value since waitpid fails with processlookuperror skip signalling a process that we know has already died the race condition can still happen if the race condition described above happens between the returncode test and the kill call suppress the race condition error bpo 40550 terminate the process with sigterm kill the process with sigkill
r

import builtins
import errno
import io
import locale
import os
import time
import signal
import sys
import threading
import warnings
import contextlib
from time import monotonic as _time
import types

try:
    import fcntl
except ImportError:
    fcntl = None


__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "getstatusoutput",
           "getoutput", "check_output", "run", "CalledProcessError", "DEVNULL",
           "SubprocessError", "TimeoutExpired", "CompletedProcess"]
           
           


try:
    import msvcrt
except ModuleNotFoundError:
    _mswindows = False
else:
    _mswindows = True


_can_fork_exec = sys.platform not in {"emscripten", "wasi"}

if _mswindows:
    import _winapi
    from _winapi import (CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP,
                         STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,
                         STD_ERROR_HANDLE, SW_HIDE,
                         STARTF_USESTDHANDLES, STARTF_USESHOWWINDOW,
                         ABOVE_NORMAL_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS,
                         HIGH_PRIORITY_CLASS, IDLE_PRIORITY_CLASS,
                         NORMAL_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS,
                         CREATE_NO_WINDOW, DETACHED_PROCESS,
                         CREATE_DEFAULT_ERROR_MODE, CREATE_BREAKAWAY_FROM_JOB)

    __all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP",
                    "STD_INPUT_HANDLE", "STD_OUTPUT_HANDLE",
                    "STD_ERROR_HANDLE", "SW_HIDE",
                    "STARTF_USESTDHANDLES", "STARTF_USESHOWWINDOW",
                    "STARTUPINFO",
                    "ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS",
                    "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS",
                    "NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS",
                    "CREATE_NO_WINDOW", "DETACHED_PROCESS",
                    "CREATE_DEFAULT_ERROR_MODE", "CREATE_BREAKAWAY_FROM_JOB"])
else:
    if _can_fork_exec:
        from _posixsubprocess import fork_exec as _fork_exec
        
        _waitpid = os.waitpid
        _waitstatus_to_exitcode = os.waitstatus_to_exitcode
        _WIFSTOPPED = os.WIFSTOPPED
        _WSTOPSIG = os.WSTOPSIG
        _WNOHANG = os.WNOHANG
    else:
        _fork_exec = None
        _waitpid = None
        _waitstatus_to_exitcode = None
        _WIFSTOPPED = None
        _WSTOPSIG = None
        _WNOHANG = None
    import select
    import selectors



class SubprocessError(Exception): pass


class CalledProcessError(SubprocessError):
    
    def __init__(self, returncode, cmd, output=None, stderr=None):
        self.returncode = returncode
        self.cmd = cmd
        self.output = output
        self.stderr = stderr

    def __str__(self):
        if self.returncode and self.returncode < 0:
            try:
                return "Command '%s' died with %r." % (
                        self.cmd, signal.Signals(-self.returncode))
            except ValueError:
                return "Command '%s' died with unknown signal %d." % (
                        self.cmd, -self.returncode)
        else:
            return "Command '%s' returned non-zero exit status %d." % (
                    self.cmd, self.returncode)

    @property
    def stdout(self):
        
        return self.output

    @stdout.setter
    def stdout(self, value):
        
        
        self.output = value


class TimeoutExpired(SubprocessError):
    
    def __init__(self, cmd, timeout, output=None, stderr=None):
        self.cmd = cmd
        self.timeout = timeout
        self.output = output
        self.stderr = stderr

    def __str__(self):
        return ("Command '%s' timed out after %s seconds" %
                (self.cmd, self.timeout))

    @property
    def stdout(self):
        return self.output

    @stdout.setter
    def stdout(self, value):
        
        
        self.output = value


if _mswindows:
    class STARTUPINFO:
        def __init__(self, *, dwFlags=0, hStdInput=None, hStdOutput=None,
                     hStdError=None, wShowWindow=0, lpAttributeList=None):
            self.dwFlags = dwFlags
            self.hStdInput = hStdInput
            self.hStdOutput = hStdOutput
            self.hStdError = hStdError
            self.wShowWindow = wShowWindow
            self.lpAttributeList = lpAttributeList or {"handle_list": []}

        def copy(self):
            attr_list = self.lpAttributeList.copy()
            if 'handle_list' in attr_list:
                attr_list['handle_list'] = list(attr_list['handle_list'])

            return STARTUPINFO(dwFlags=self.dwFlags,
                               hStdInput=self.hStdInput,
                               hStdOutput=self.hStdOutput,
                               hStdError=self.hStdError,
                               wShowWindow=self.wShowWindow,
                               lpAttributeList=attr_list)


    class Handle(int):
        closed = False

        def Close(self, CloseHandle=_winapi.CloseHandle):
            if not self.closed:
                self.closed = True
                CloseHandle(self)

        def Detach(self):
            if not self.closed:
                self.closed = True
                return int(self)
            raise ValueError("already closed")

        def __repr__(self):
            return "%s(%d)" % (self.__class__.__name__, int(self))

        __del__ = Close
else:
    
    
    
    _PIPE_BUF = getattr(select, 'PIPE_BUF', 512)

    
    
    
    if hasattr(selectors, 'PollSelector'):
        _PopenSelector = selectors.PollSelector
    else:
        _PopenSelector = selectors.SelectSelector


if _mswindows:
    
    
    
    
    
    
    
    
    _active = None

    def _cleanup():
        pass
else:
    
    
    
    
    _active = []

    def _cleanup():
        if _active is None:
            return
        for inst in _active[:]:
            res = inst._internal_poll(_deadstate=sys.maxsize)
            if res is not None:
                try:
                    _active.remove(inst)
                except ValueError:
                    
                    
                    pass

PIPE = -1
STDOUT = -2
DEVNULL = -3






def _optim_args_from_interpreter_flags():
    
    args = []
    value = sys.flags.optimize
    if value > 0:
        args.append('-' + 'O' * value)
    return args


def _args_from_interpreter_flags():
    
    flag_opt_map = {
        'debug': 'd',
        
        
        'dont_write_bytecode': 'B',
        'no_site': 'S',
        'verbose': 'v',
        'bytes_warning': 'b',
        'quiet': 'q',
        
    }
    args = _optim_args_from_interpreter_flags()
    for flag, opt in flag_opt_map.items():
        v = getattr(sys.flags, flag)
        if v > 0:
            args.append('-' + opt * v)

    if sys.flags.isolated:
        args.append('-I')
    else:
        if sys.flags.ignore_environment:
            args.append('-E')
        if sys.flags.no_user_site:
            args.append('-s')
        if sys.flags.safe_path:
            args.append('-P')

    
    warnopts = sys.warnoptions[:]
    xoptions = getattr(sys, '_xoptions', {})
    bytes_warning = sys.flags.bytes_warning
    dev_mode = sys.flags.dev_mode

    if bytes_warning > 1:
        warnopts.remove("error::BytesWarning")
    elif bytes_warning:
        warnopts.remove("default::BytesWarning")
    if dev_mode:
        warnopts.remove('default')
    for opt in warnopts:
        args.append('-W' + opt)

    
    if dev_mode:
        args.extend(('-X', 'dev'))
    for opt in ('faulthandler', 'tracemalloc', 'importtime',
                'frozen_modules', 'showrefcount', 'utf8'):
        if opt in xoptions:
            value = xoptions[opt]
            if value is True:
                arg = opt
            else:
                arg = '%s=%s' % (opt, value)
            args.extend(('-X', arg))

    return args


def _text_encoding():
    
    
    if sys.flags.warn_default_encoding:
        f = sys._getframe()
        filename = f.f_code.co_filename
        stacklevel = 2
        while f := f.f_back:
            if f.f_code.co_filename != filename:
                break
            stacklevel += 1
        warnings.warn("'encoding' argument not specified.",
                      EncodingWarning, stacklevel)

    if sys.flags.utf8_mode:
        return "utf-8"
    else:
        return locale.getencoding()


def call(*popenargs, timeout=None, **kwargs):
    
    with Popen(*popenargs, **kwargs) as p:
        try:
            return p.wait(timeout=timeout)
        except:  
            p.kill()
            
            raise


def check_call(*popenargs, **kwargs):
    
    retcode = call(*popenargs, **kwargs)
    if retcode:
        cmd = kwargs.get("args")
        if cmd is None:
            cmd = popenargs[0]
        raise CalledProcessError(retcode, cmd)
    return 0


def check_output(*popenargs, timeout=None, **kwargs):
    r
    for kw in ('stdout', 'check'):
        if kw in kwargs:
            raise ValueError(f'{kw} argument not allowed, it will be overridden.')

    if 'input' in kwargs and kwargs['input'] is None:
        
        
        if kwargs.get('universal_newlines') or kwargs.get('text') or kwargs.get('encoding') \
                or kwargs.get('errors'):
            empty = ''
        else:
            empty = b''
        kwargs['input'] = empty

    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
               **kwargs).stdout


class CompletedProcess(object):
    
    def __init__(self, args, returncode, stdout=None, stderr=None):
        self.args = args
        self.returncode = returncode
        self.stdout = stdout
        self.stderr = stderr

    def __repr__(self):
        args = ['args={!r}'.format(self.args),
                'returncode={!r}'.format(self.returncode)]
        if self.stdout is not None:
            args.append('stdout={!r}'.format(self.stdout))
        if self.stderr is not None:
            args.append('stderr={!r}'.format(self.stderr))
        return "{}({})".format(type(self).__name__, ', '.join(args))

    __class_getitem__ = classmethod(types.GenericAlias)


    def check_returncode(self):
        
        if self.returncode:
            raise CalledProcessError(self.returncode, self.args, self.stdout,
                                     self.stderr)


def run(*popenargs,
        input=None, capture_output=False, timeout=None, check=False, **kwargs):
    
    if input is not None:
        if kwargs.get('stdin') is not None:
            raise ValueError('stdin and input arguments may not both be used.')
        kwargs['stdin'] = PIPE

    if capture_output:
        if kwargs.get('stdout') is not None or kwargs.get('stderr') is not None:
            raise ValueError('stdout and stderr arguments may not be used '
                             'with capture_output.')
        kwargs['stdout'] = PIPE
        kwargs['stderr'] = PIPE

    with Popen(*popenargs, **kwargs) as process:
        try:
            stdout, stderr = process.communicate(input, timeout=timeout)
        except TimeoutExpired as exc:
            process.kill()
            if _mswindows:
                
                
                
                
                
                exc.stdout, exc.stderr = process.communicate()
            else:
                
                
                process.wait()
            raise
        except:  
            process.kill()
            
            raise
        retcode = process.poll()
        if check and retcode:
            raise CalledProcessError(retcode, process.args,
                                     output=stdout, stderr=stderr)
    return CompletedProcess(process.args, retcode, stdout, stderr)


def list2cmdline(seq):
    

    
    
    
    
    result = []
    needquote = False
    for arg in map(os.fsdecode, seq):
        bs_buf = []

        
        if result:
            result.append(' ')

        needquote = (" " in arg) or ("\t" in arg) or not arg
        if needquote:
            result.append('"')

        for c in arg:
            if c == '\\':
                
                bs_buf.append(c)
            elif c == '"':
                
                result.append('\\' * len(bs_buf)*2)
                bs_buf = []
                result.append('\\"')
            else:
                
                if bs_buf:
                    result.extend(bs_buf)
                    bs_buf = []
                result.append(c)

        
        if bs_buf:
            result.extend(bs_buf)

        if needquote:
            result.extend(bs_buf)
            result.append('"')

    return ''.join(result)





def getstatusoutput(cmd, *, encoding=None, errors=None):
    
    try:
        data = check_output(cmd, shell=True, text=True, stderr=STDOUT,
                            encoding=encoding, errors=errors)
        exitcode = 0
    except CalledProcessError as ex:
        data = ex.output
        exitcode = ex.returncode
    if data[-1:] == '\n':
        data = data[:-1]
    return exitcode, data

def getoutput(cmd, *, encoding=None, errors=None):
    
    return getstatusoutput(cmd, encoding=encoding, errors=errors)[1]



def _use_posix_spawn():
    
    if _mswindows or not hasattr(os, 'posix_spawn'):
        
        return False

    if sys.platform in ('darwin', 'sunos5'):
        
        
        return True

    
    try:
        ver = os.confstr('CS_GNU_LIBC_VERSION')
        
        parts = ver.split(maxsplit=1)
        if len(parts) != 2:
            
            raise ValueError
        libc = parts[0]
        version = tuple(map(int, parts[1].split('.')))

        if sys.platform == 'linux' and libc == 'glibc' and version >= (2, 24):
            
            
            return True
        
        
        
    except (AttributeError, ValueError, OSError):
        
        pass

    
    return False




_USE_POSIX_SPAWN = _use_posix_spawn()
_USE_VFORK = True


class Popen:
    
    _child_created = False  

    def __init__(self, args, bufsize=-1, executable=None,
                 stdin=None, stdout=None, stderr=None,
                 preexec_fn=None, close_fds=True,
                 shell=False, cwd=None, env=None, universal_newlines=None,
                 startupinfo=None, creationflags=0,
                 restore_signals=True, start_new_session=False,
                 pass_fds=(), *, user=None, group=None, extra_groups=None,
                 encoding=None, errors=None, text=None, umask=-1, pipesize=-1,
                 process_group=None):
        
        if not _can_fork_exec:
            raise OSError(
                errno.ENOTSUP, f"{sys.platform} does not support processes."
            )

        _cleanup()
        
        
        
        
        
        self._waitpid_lock = threading.Lock()

        self._input = None
        self._communication_started = False
        if bufsize is None:
            bufsize = -1  
        if not isinstance(bufsize, int):
            raise TypeError("bufsize must be an integer")

        if pipesize is None:
            pipesize = -1  
        if not isinstance(pipesize, int):
            raise TypeError("pipesize must be an integer")

        if _mswindows:
            if preexec_fn is not None:
                raise ValueError("preexec_fn is not supported on Windows "
                                 "platforms")
        else:
            
            if pass_fds and not close_fds:
                warnings.warn("pass_fds overriding close_fds.", RuntimeWarning)
                close_fds = True
            if startupinfo is not None:
                raise ValueError("startupinfo is only supported on Windows "
                                 "platforms")
            if creationflags != 0:
                raise ValueError("creationflags is only supported on Windows "
                                 "platforms")

        self.args = args
        self.stdin = None
        self.stdout = None
        self.stderr = None
        self.pid = None
        self.returncode = None
        self.encoding = encoding
        self.errors = errors
        self.pipesize = pipesize

        
        if (text is not None and universal_newlines is not None
            and bool(universal_newlines) != bool(text)):
            raise SubprocessError('Cannot disambiguate when both text '
                                  'and universal_newlines are supplied but '
                                  'different. Pass one or the other.')

        self.text_mode = encoding or errors or text or universal_newlines
        if self.text_mode and encoding is None:
            self.encoding = encoding = _text_encoding()

        
        
        
        self._sigint_wait_secs = 0.25  

        self._closed_child_pipe_fds = False

        if self.text_mode:
            if bufsize == 1:
                line_buffering = True
                
                
                bufsize = -1
            else:
                line_buffering = False

        if process_group is None:
            process_group = -1  

        gid = None
        if group is not None:
            if not hasattr(os, 'setregid'):
                raise ValueError("The 'group' parameter is not supported on the "
                                 "current platform")

            elif isinstance(group, str):
                try:
                    import grp
                except ImportError:
                    raise ValueError("The group parameter cannot be a string "
                                     "on systems without the grp module")

                gid = grp.getgrnam(group).gr_gid
            elif isinstance(group, int):
                gid = group
            else:
                raise TypeError("Group must be a string or an integer, not {}"
                                .format(type(group)))

            if gid < 0:
                raise ValueError(f"Group ID cannot be negative, got {gid}")

        gids = None
        if extra_groups is not None:
            if not hasattr(os, 'setgroups'):
                raise ValueError("The 'extra_groups' parameter is not "
                                 "supported on the current platform")

            elif isinstance(extra_groups, str):
                raise ValueError("Groups must be a list, not a string")

            gids = []
            for extra_group in extra_groups:
                if isinstance(extra_group, str):
                    try:
                        import grp
                    except ImportError:
                        raise ValueError("Items in extra_groups cannot be "
                                         "strings on systems without the "
                                         "grp module")

                    gids.append(grp.getgrnam(extra_group).gr_gid)
                elif isinstance(extra_group, int):
                    gids.append(extra_group)
                else:
                    raise TypeError("Items in extra_groups must be a string "
                                    "or integer, not {}"
                                    .format(type(extra_group)))

            
            
            for gid_check in gids:
                if gid_check < 0:
                    raise ValueError(f"Group ID cannot be negative, got {gid_check}")

        uid = None
        if user is not None:
            if not hasattr(os, 'setreuid'):
                raise ValueError("The 'user' parameter is not supported on "
                                 "the current platform")

            elif isinstance(user, str):
                try:
                    import pwd
                except ImportError:
                    raise ValueError("The user parameter cannot be a string "
                                     "on systems without the pwd module")
                uid = pwd.getpwnam(user).pw_uid
            elif isinstance(user, int):
                uid = user
            else:
                raise TypeError("User must be a string or an integer")

            if uid < 0:
                raise ValueError(f"User ID cannot be negative, got {uid}")

        
        
        
        
        
        
        
        
        
        
        
        
        
        

        (p2cread, p2cwrite,
         c2pread, c2pwrite,
         errread, errwrite) = self._get_handles(stdin, stdout, stderr)

        

        
        
        

        if _mswindows:
            if p2cwrite != -1:
                p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0)
            if c2pread != -1:
                c2pread = msvcrt.open_osfhandle(c2pread.Detach(), 0)
            if errread != -1:
                errread = msvcrt.open_osfhandle(errread.Detach(), 0)

        try:
            if p2cwrite != -1:
                self.stdin = io.open(p2cwrite, 'wb', bufsize)
                if self.text_mode:
                    self.stdin = io.TextIOWrapper(self.stdin, write_through=True,
                            line_buffering=line_buffering,
                            encoding=encoding, errors=errors)
            if c2pread != -1:
                self.stdout = io.open(c2pread, 'rb', bufsize)
                if self.text_mode:
                    self.stdout = io.TextIOWrapper(self.stdout,
                            encoding=encoding, errors=errors)
            if errread != -1:
                self.stderr = io.open(errread, 'rb', bufsize)
                if self.text_mode:
                    self.stderr = io.TextIOWrapper(self.stderr,
                            encoding=encoding, errors=errors)

            self._execute_child(args, executable, preexec_fn, close_fds,
                                pass_fds, cwd, env,
                                startupinfo, creationflags, shell,
                                p2cread, p2cwrite,
                                c2pread, c2pwrite,
                                errread, errwrite,
                                restore_signals,
                                gid, gids, uid, umask,
                                start_new_session, process_group)
        except:
            
            for f in filter(None, (self.stdin, self.stdout, self.stderr)):
                try:
                    f.close()
                except OSError:
                    pass  

            if not self._closed_child_pipe_fds:
                to_close = []
                if stdin == PIPE:
                    to_close.append(p2cread)
                if stdout == PIPE:
                    to_close.append(c2pwrite)
                if stderr == PIPE:
                    to_close.append(errwrite)
                if hasattr(self, '_devnull'):
                    to_close.append(self._devnull)
                for fd in to_close:
                    try:
                        if _mswindows and isinstance(fd, Handle):
                            fd.Close()
                        else:
                            os.close(fd)
                    except OSError:
                        pass

            raise

    def __repr__(self):
        obj_repr = (
            f"<{self.__class__.__name__}: "
            f"returncode: {self.returncode} args: {self.args!r}>"
        )
        if len(obj_repr) > 80:
            obj_repr = obj_repr[:76] + "...>"
        return obj_repr

    __class_getitem__ = classmethod(types.GenericAlias)

    @property
    def universal_newlines(self):
        
        
        return self.text_mode

    @universal_newlines.setter
    def universal_newlines(self, universal_newlines):
        self.text_mode = bool(universal_newlines)

    def _translate_newlines(self, data, encoding, errors):
        data = data.decode(encoding, errors)
        return data.replace("\r\n", "\n").replace("\r", "\n")

    def __enter__(self):
        return self

    def __exit__(self, exc_type, value, traceback):
        if self.stdout:
            self.stdout.close()
        if self.stderr:
            self.stderr.close()
        try:  
            if self.stdin:
                self.stdin.close()
        finally:
            if exc_type == KeyboardInterrupt:
                
                
                
                
                
                
                
                if self._sigint_wait_secs > 0:
                    try:
                        self._wait(timeout=self._sigint_wait_secs)
                    except TimeoutExpired:
                        pass
                self._sigint_wait_secs = 0  
                return  

            
            self.wait()

    def __del__(self, _maxsize=sys.maxsize, _warn=warnings.warn):
        if not self._child_created:
            
            return
        if self.returncode is None:
            
            
            _warn("subprocess %s is still running" % self.pid,
                  ResourceWarning, source=self)
        
        self._internal_poll(_deadstate=_maxsize)
        if self.returncode is None and _active is not None:
            
            _active.append(self)

    def _get_devnull(self):
        if not hasattr(self, '_devnull'):
            self._devnull = os.open(os.devnull, os.O_RDWR)
        return self._devnull

    def _stdin_write(self, input):
        if input:
            try:
                self.stdin.write(input)
            except BrokenPipeError:
                pass  
            except OSError as exc:
                if exc.errno == errno.EINVAL:
                    
                    
                    
                    pass
                else:
                    raise

        try:
            self.stdin.close()
        except BrokenPipeError:
            pass  
        except OSError as exc:
            if exc.errno == errno.EINVAL:
                pass
            else:
                raise

    def communicate(self, input=None, timeout=None):
        

        if self._communication_started and input:
            raise ValueError("Cannot send input after starting communication")

        
        
        
        if (timeout is None and not self._communication_started and
            [self.stdin, self.stdout, self.stderr].count(None) >= 2):
            stdout = None
            stderr = None
            if self.stdin:
                self._stdin_write(input)
            elif self.stdout:
                stdout = self.stdout.read()
                self.stdout.close()
            elif self.stderr:
                stderr = self.stderr.read()
                self.stderr.close()
            self.wait()
        else:
            if timeout is not None:
                endtime = _time() + timeout
            else:
                endtime = None

            try:
                stdout, stderr = self._communicate(input, endtime, timeout)
            except KeyboardInterrupt:
                
                
                if timeout is not None:
                    sigint_timeout = min(self._sigint_wait_secs,
                                         self._remaining_time(endtime))
                else:
                    sigint_timeout = self._sigint_wait_secs
                self._sigint_wait_secs = 0  
                try:
                    self._wait(timeout=sigint_timeout)
                except TimeoutExpired:
                    pass
                raise  

            finally:
                self._communication_started = True

            sts = self.wait(timeout=self._remaining_time(endtime))

        return (stdout, stderr)


    def poll(self):
        
        return self._internal_poll()


    def _remaining_time(self, endtime):
        
        if endtime is None:
            return None
        else:
            return endtime - _time()


    def _check_timeout(self, endtime, orig_timeout, stdout_seq, stderr_seq,
                       skip_check_and_raise=False):
        
        if endtime is None:
            return
        if skip_check_and_raise or _time() > endtime:
            raise TimeoutExpired(
                    self.args, orig_timeout,
                    output=b''.join(stdout_seq) if stdout_seq else None,
                    stderr=b''.join(stderr_seq) if stderr_seq else None)


    def wait(self, timeout=None):
        
        if timeout is not None:
            endtime = _time() + timeout
        try:
            return self._wait(timeout=timeout)
        except KeyboardInterrupt:
            
            
            
            
            if timeout is not None:
                sigint_timeout = min(self._sigint_wait_secs,
                                     self._remaining_time(endtime))
            else:
                sigint_timeout = self._sigint_wait_secs
            self._sigint_wait_secs = 0  
            try:
                self._wait(timeout=sigint_timeout)
            except TimeoutExpired:
                pass
            raise  

    def _close_pipe_fds(self,
                        p2cread, p2cwrite,
                        c2pread, c2pwrite,
                        errread, errwrite):
        
        devnull_fd = getattr(self, '_devnull', None)

        with contextlib.ExitStack() as stack:
            if _mswindows:
                if p2cread != -1:
                    stack.callback(p2cread.Close)
                if c2pwrite != -1:
                    stack.callback(c2pwrite.Close)
                if errwrite != -1:
                    stack.callback(errwrite.Close)
            else:
                if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd:
                    stack.callback(os.close, p2cread)
                if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd:
                    stack.callback(os.close, c2pwrite)
                if errwrite != -1 and errread != -1 and errwrite != devnull_fd:
                    stack.callback(os.close, errwrite)

            if devnull_fd is not None:
                stack.callback(os.close, devnull_fd)

        
        self._closed_child_pipe_fds = True

    @contextlib.contextmanager
    def _on_error_fd_closer(self):
        
        to_close = []
        try:
            yield to_close
        except:
            if hasattr(self, '_devnull'):
                to_close.append(self._devnull)
                del self._devnull
            for fd in to_close:
                try:
                    if _mswindows and isinstance(fd, Handle):
                        fd.Close()
                    else:
                        os.close(fd)
                except OSError:
                    pass
            raise

    if _mswindows:
        
        
        
        def _get_handles(self, stdin, stdout, stderr):
            
            if stdin is None and stdout is None and stderr is None:
                return (-1, -1, -1, -1, -1, -1)

            p2cread, p2cwrite = -1, -1
            c2pread, c2pwrite = -1, -1
            errread, errwrite = -1, -1

            with self._on_error_fd_closer() as err_close_fds:
                if stdin is None:
                    p2cread = _winapi.GetStdHandle(_winapi.STD_INPUT_HANDLE)
                    if p2cread is None:
                        p2cread, _ = _winapi.CreatePipe(None, 0)
                        p2cread = Handle(p2cread)
                        err_close_fds.append(p2cread)
                        _winapi.CloseHandle(_)
                elif stdin == PIPE:
                    p2cread, p2cwrite = _winapi.CreatePipe(None, 0)
                    p2cread, p2cwrite = Handle(p2cread), Handle(p2cwrite)
                    err_close_fds.extend((p2cread, p2cwrite))
                elif stdin == DEVNULL:
                    p2cread = msvcrt.get_osfhandle(self._get_devnull())
                elif isinstance(stdin, int):
                    p2cread = msvcrt.get_osfhandle(stdin)
                else:
                    
                    p2cread = msvcrt.get_osfhandle(stdin.fileno())
                p2cread = self._make_inheritable(p2cread)

                if stdout is None:
                    c2pwrite = _winapi.GetStdHandle(_winapi.STD_OUTPUT_HANDLE)
                    if c2pwrite is None:
                        _, c2pwrite = _winapi.CreatePipe(None, 0)
                        c2pwrite = Handle(c2pwrite)
                        err_close_fds.append(c2pwrite)
                        _winapi.CloseHandle(_)
                elif stdout == PIPE:
                    c2pread, c2pwrite = _winapi.CreatePipe(None, 0)
                    c2pread, c2pwrite = Handle(c2pread), Handle(c2pwrite)
                    err_close_fds.extend((c2pread, c2pwrite))
                elif stdout == DEVNULL:
                    c2pwrite = msvcrt.get_osfhandle(self._get_devnull())
                elif isinstance(stdout, int):
                    c2pwrite = msvcrt.get_osfhandle(stdout)
                else:
                    
                    c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
                c2pwrite = self._make_inheritable(c2pwrite)

                if stderr is None:
                    errwrite = _winapi.GetStdHandle(_winapi.STD_ERROR_HANDLE)
                    if errwrite is None:
                        _, errwrite = _winapi.CreatePipe(None, 0)
                        errwrite = Handle(errwrite)
                        err_close_fds.append(errwrite)
                        _winapi.CloseHandle(_)
                elif stderr == PIPE:
                    errread, errwrite = _winapi.CreatePipe(None, 0)
                    errread, errwrite = Handle(errread), Handle(errwrite)
                    err_close_fds.extend((errread, errwrite))
                elif stderr == STDOUT:
                    errwrite = c2pwrite
                elif stderr == DEVNULL:
                    errwrite = msvcrt.get_osfhandle(self._get_devnull())
                elif isinstance(stderr, int):
                    errwrite = msvcrt.get_osfhandle(stderr)
                else:
                    
                    errwrite = msvcrt.get_osfhandle(stderr.fileno())
                errwrite = self._make_inheritable(errwrite)

            return (p2cread, p2cwrite,
                    c2pread, c2pwrite,
                    errread, errwrite)


        def _make_inheritable(self, handle):
            
            h = _winapi.DuplicateHandle(
                _winapi.GetCurrentProcess(), handle,
                _winapi.GetCurrentProcess(), 0, 1,
                _winapi.DUPLICATE_SAME_ACCESS)
            return Handle(h)


        def _filter_handle_list(self, handle_list):
            
            
            
            
            return list({handle for handle in handle_list
                         if handle & 0x3 != 0x3
                         or _winapi.GetFileType(handle) !=
                            _winapi.FILE_TYPE_CHAR})


        def _execute_child(self, args, executable, preexec_fn, close_fds,
                           pass_fds, cwd, env,
                           startupinfo, creationflags, shell,
                           p2cread, p2cwrite,
                           c2pread, c2pwrite,
                           errread, errwrite,
                           unused_restore_signals,
                           unused_gid, unused_gids, unused_uid,
                           unused_umask,
                           unused_start_new_session, unused_process_group):
            

            assert not pass_fds, "pass_fds not supported on Windows."

            if isinstance(args, str):
                pass
            elif isinstance(args, bytes):
                if shell:
                    raise TypeError('bytes args is not allowed on Windows')
                args = list2cmdline([args])
            elif isinstance(args, os.PathLike):
                if shell:
                    raise TypeError('path-like args is not allowed when '
                                    'shell is true')
                args = list2cmdline([args])
            else:
                args = list2cmdline(args)

            if executable is not None:
                executable = os.fsdecode(executable)

            
            if startupinfo is None:
                startupinfo = STARTUPINFO()
            else:
                
                
                startupinfo = startupinfo.copy()

            use_std_handles = -1 not in (p2cread, c2pwrite, errwrite)
            if use_std_handles:
                startupinfo.dwFlags |= _winapi.STARTF_USESTDHANDLES
                startupinfo.hStdInput = p2cread
                startupinfo.hStdOutput = c2pwrite
                startupinfo.hStdError = errwrite

            attribute_list = startupinfo.lpAttributeList
            have_handle_list = bool(attribute_list and
                                    "handle_list" in attribute_list and
                                    attribute_list["handle_list"])

            
            if have_handle_list or (use_std_handles and close_fds):
                if attribute_list is None:
                    attribute_list = startupinfo.lpAttributeList = {}
                handle_list = attribute_list["handle_list"] = \
                    list(attribute_list.get("handle_list", []))

                if use_std_handles:
                    handle_list += [int(p2cread), int(c2pwrite), int(errwrite)]

                handle_list[:] = self._filter_handle_list(handle_list)

                if handle_list:
                    if not close_fds:
                        warnings.warn("startupinfo.lpAttributeList['handle_list'] "
                                      "overriding close_fds", RuntimeWarning)

                    
                    
                    
                    close_fds = False

            if shell:
                startupinfo.dwFlags |= _winapi.STARTF_USESHOWWINDOW
                startupinfo.wShowWindow = _winapi.SW_HIDE
                if not executable:
                    
                    
                    
                    
                    
                    comspec = os.environ.get('ComSpec')
                    if not comspec:
                        system_root = os.environ.get('SystemRoot', '')
                        comspec = os.path.join(system_root, 'System32', 'cmd.exe')
                        if not os.path.isabs(comspec):
                            raise FileNotFoundError('shell not found: neither %ComSpec% nor %SystemRoot% is set')
                    if os.path.isabs(comspec):
                        executable = comspec
                else:
                    comspec = executable

                args = '{} /c "{}"'.format (comspec, args)

            if cwd is not None:
                cwd = os.fsdecode(cwd)

            sys.audit("subprocess.Popen", executable, args, cwd, env)

            
            try:
                hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
                                         
                                         None, None,
                                         int(not close_fds),
                                         creationflags,
                                         env,
                                         cwd,
                                         startupinfo)
            finally:
                
                
                
                
                
                
                self._close_pipe_fds(p2cread, p2cwrite,
                                     c2pread, c2pwrite,
                                     errread, errwrite)

            
            self._child_created = True
            self._handle = Handle(hp)
            self.pid = pid
            _winapi.CloseHandle(ht)

        def _internal_poll(self, _deadstate=None,
                _WaitForSingleObject=_winapi.WaitForSingleObject,
                _WAIT_OBJECT_0=_winapi.WAIT_OBJECT_0,
                _GetExitCodeProcess=_winapi.GetExitCodeProcess):
            
            if self.returncode is None:
                if _WaitForSingleObject(self._handle, 0) == _WAIT_OBJECT_0:
                    self.returncode = _GetExitCodeProcess(self._handle)
            return self.returncode


        def _wait(self, timeout):
            
            if timeout is None:
                timeout_millis = _winapi.INFINITE
            else:
                timeout_millis = int(timeout * 1000)
            if self.returncode is None:
                
                result = _winapi.WaitForSingleObject(self._handle,
                                                     timeout_millis)
                if result == _winapi.WAIT_TIMEOUT:
                    raise TimeoutExpired(self.args, timeout)
                self.returncode = _winapi.GetExitCodeProcess(self._handle)
            return self.returncode


        def _readerthread(self, fh, buffer):
            buffer.append(fh.read())
            fh.close()


        def _communicate(self, input, endtime, orig_timeout):
            
            
            if self.stdout and not hasattr(self, "_stdout_buff"):
                self._stdout_buff = []
                self.stdout_thread = \
                        threading.Thread(target=self._readerthread,
                                         args=(self.stdout, self._stdout_buff))
                self.stdout_thread.daemon = True
                self.stdout_thread.start()
            if self.stderr and not hasattr(self, "_stderr_buff"):
                self._stderr_buff = []
                self.stderr_thread = \
                        threading.Thread(target=self._readerthread,
                                         args=(self.stderr, self._stderr_buff))
                self.stderr_thread.daemon = True
                self.stderr_thread.start()

            if self.stdin:
                self._stdin_write(input)

            
            
            
            if self.stdout is not None:
                self.stdout_thread.join(self._remaining_time(endtime))
                if self.stdout_thread.is_alive():
                    raise TimeoutExpired(self.args, orig_timeout)
            if self.stderr is not None:
                self.stderr_thread.join(self._remaining_time(endtime))
                if self.stderr_thread.is_alive():
                    raise TimeoutExpired(self.args, orig_timeout)

            
            
            stdout = None
            stderr = None
            if self.stdout:
                stdout = self._stdout_buff
                self.stdout.close()
            if self.stderr:
                stderr = self._stderr_buff
                self.stderr.close()

            
            stdout = stdout[0] if stdout else None
            stderr = stderr[0] if stderr else None

            return (stdout, stderr)

        def send_signal(self, sig):
            
            
            if self.returncode is not None:
                return
            if sig == signal.SIGTERM:
                self.terminate()
            elif sig == signal.CTRL_C_EVENT:
                os.kill(self.pid, signal.CTRL_C_EVENT)
            elif sig == signal.CTRL_BREAK_EVENT:
                os.kill(self.pid, signal.CTRL_BREAK_EVENT)
            else:
                raise ValueError("Unsupported signal: {}".format(sig))

        def terminate(self):
            
            
            if self.returncode is not None:
                return
            try:
                _winapi.TerminateProcess(self._handle, 1)
            except PermissionError:
                
                
                rc = _winapi.GetExitCodeProcess(self._handle)
                if rc == _winapi.STILL_ACTIVE:
                    raise
                self.returncode = rc

        kill = terminate

    else:
        
        
        
        def _get_handles(self, stdin, stdout, stderr):
            
            p2cread, p2cwrite = -1, -1
            c2pread, c2pwrite = -1, -1
            errread, errwrite = -1, -1

            with self._on_error_fd_closer() as err_close_fds:
                if stdin is None:
                    pass
                elif stdin == PIPE:
                    p2cread, p2cwrite = os.pipe()
                    err_close_fds.extend((p2cread, p2cwrite))
                    if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"):
                        fcntl.fcntl(p2cwrite, fcntl.F_SETPIPE_SZ, self.pipesize)
                elif stdin == DEVNULL:
                    p2cread = self._get_devnull()
                elif isinstance(stdin, int):
                    p2cread = stdin
                else:
                    
                    p2cread = stdin.fileno()

                if stdout is None:
                    pass
                elif stdout == PIPE:
                    c2pread, c2pwrite = os.pipe()
                    err_close_fds.extend((c2pread, c2pwrite))
                    if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"):
                        fcntl.fcntl(c2pwrite, fcntl.F_SETPIPE_SZ, self.pipesize)
                elif stdout == DEVNULL:
                    c2pwrite = self._get_devnull()
                elif isinstance(stdout, int):
                    c2pwrite = stdout
                else:
                    
                    c2pwrite = stdout.fileno()

                if stderr is None:
                    pass
                elif stderr == PIPE:
                    errread, errwrite = os.pipe()
                    err_close_fds.extend((errread, errwrite))
                    if self.pipesize > 0 and hasattr(fcntl, "F_SETPIPE_SZ"):
                        fcntl.fcntl(errwrite, fcntl.F_SETPIPE_SZ, self.pipesize)
                elif stderr == STDOUT:
                    if c2pwrite != -1:
                        errwrite = c2pwrite
                    else: 
                        errwrite = sys.__stdout__.fileno()
                elif stderr == DEVNULL:
                    errwrite = self._get_devnull()
                elif isinstance(stderr, int):
                    errwrite = stderr
                else:
                    
                    errwrite = stderr.fileno()

            return (p2cread, p2cwrite,
                    c2pread, c2pwrite,
                    errread, errwrite)


        def _posix_spawn(self, args, executable, env, restore_signals,
                         p2cread, p2cwrite,
                         c2pread, c2pwrite,
                         errread, errwrite):
            
            if env is None:
                env = os.environ

            kwargs = {}
            if restore_signals:
                
                sigset = []
                for signame in ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ'):
                    signum = getattr(signal, signame, None)
                    if signum is not None:
                        sigset.append(signum)
                kwargs['setsigdef'] = sigset

            file_actions = []
            for fd in (p2cwrite, c2pread, errread):
                if fd != -1:
                    file_actions.append((os.POSIX_SPAWN_CLOSE, fd))
            for fd, fd2 in (
                (p2cread, 0),
                (c2pwrite, 1),
                (errwrite, 2),
            ):
                if fd != -1:
                    file_actions.append((os.POSIX_SPAWN_DUP2, fd, fd2))
            if file_actions:
                kwargs['file_actions'] = file_actions

            self.pid = os.posix_spawn(executable, args, env, **kwargs)
            self._child_created = True

            self._close_pipe_fds(p2cread, p2cwrite,
                                 c2pread, c2pwrite,
                                 errread, errwrite)

        def _execute_child(self, args, executable, preexec_fn, close_fds,
                           pass_fds, cwd, env,
                           startupinfo, creationflags, shell,
                           p2cread, p2cwrite,
                           c2pread, c2pwrite,
                           errread, errwrite,
                           restore_signals,
                           gid, gids, uid, umask,
                           start_new_session, process_group):
            

            if isinstance(args, (str, bytes)):
                args = [args]
            elif isinstance(args, os.PathLike):
                if shell:
                    raise TypeError('path-like args is not allowed when '
                                    'shell is true')
                args = [args]
            else:
                args = list(args)

            if shell:
                
                unix_shell = ('/system/bin/sh' if
                          hasattr(sys, 'getandroidapilevel') else '/bin/sh')
                args = [unix_shell, "-c"] + args
                if executable:
                    args[0] = executable

            if executable is None:
                executable = args[0]

            sys.audit("subprocess.Popen", executable, args, cwd, env)

            if (_USE_POSIX_SPAWN
                    and os.path.dirname(executable)
                    and preexec_fn is None
                    and not close_fds
                    and not pass_fds
                    and cwd is None
                    and (p2cread == -1 or p2cread > 2)
                    and (c2pwrite == -1 or c2pwrite > 2)
                    and (errwrite == -1 or errwrite > 2)
                    and not start_new_session
                    and process_group == -1
                    and gid is None
                    and gids is None
                    and uid is None
                    and umask < 0):
                self._posix_spawn(args, executable, env, restore_signals,
                                  p2cread, p2cwrite,
                                  c2pread, c2pwrite,
                                  errread, errwrite)
                return

            orig_executable = executable

            
            
            
            errpipe_read, errpipe_write = os.pipe()
            
            low_fds_to_close = []
            while errpipe_write < 3:
                low_fds_to_close.append(errpipe_write)
                errpipe_write = os.dup(errpipe_write)
            for low_fd in low_fds_to_close:
                os.close(low_fd)
            try:
                try:
                    
                    
                    
                    

                    if env is not None:
                        env_list = []
                        for k, v in env.items():
                            k = os.fsencode(k)
                            if b'=' in k:
                                raise ValueError("illegal environment variable name")
                            env_list.append(k + b'=' + os.fsencode(v))
                    else:
                        env_list = None  
                    executable = os.fsencode(executable)
                    if os.path.dirname(executable):
                        executable_list = (executable,)
                    else:
                        
                        executable_list = tuple(
                            os.path.join(os.fsencode(dir), executable)
                            for dir in os.get_exec_path(env))
                    fds_to_keep = set(pass_fds)
                    fds_to_keep.add(errpipe_write)
                    self.pid = _fork_exec(
                            args, executable_list,
                            close_fds, tuple(sorted(map(int, fds_to_keep))),
                            cwd, env_list,
                            p2cread, p2cwrite, c2pread, c2pwrite,
                            errread, errwrite,
                            errpipe_read, errpipe_write,
                            restore_signals, start_new_session,
                            process_group, gid, gids, uid, umask,
                            preexec_fn, _USE_VFORK)
                    self._child_created = True
                finally:
                    
                    os.close(errpipe_write)

                self._close_pipe_fds(p2cread, p2cwrite,
                                     c2pread, c2pwrite,
                                     errread, errwrite)

                
                
                errpipe_data = bytearray()
                while True:
                    part = os.read(errpipe_read, 50000)
                    errpipe_data += part
                    if not part or len(errpipe_data) > 50000:
                        break
            finally:
                
                os.close(errpipe_read)

            if errpipe_data:
                try:
                    pid, sts = os.waitpid(self.pid, 0)
                    if pid == self.pid:
                        self._handle_exitstatus(sts)
                    else:
                        self.returncode = sys.maxsize
                except ChildProcessError:
                    pass

                try:
                    exception_name, hex_errno, err_msg = (
                            errpipe_data.split(b':', 2))
                    
                    
                    
                    err_msg = err_msg.decode()
                except ValueError:
                    exception_name = b'SubprocessError'
                    hex_errno = b'0'
                    err_msg = 'Bad exception data from child: {!r}'.format(
                                  bytes(errpipe_data))
                child_exception_type = getattr(
                        builtins, exception_name.decode('ascii'),
                        SubprocessError)
                if issubclass(child_exception_type, OSError) and hex_errno:
                    errno_num = int(hex_errno, 16)
                    child_exec_never_called = (err_msg == "noexec")
                    if child_exec_never_called:
                        err_msg = ""
                        
                        err_filename = cwd
                    else:
                        err_filename = orig_executable
                    if errno_num != 0:
                        err_msg = os.strerror(errno_num)
                    raise child_exception_type(errno_num, err_msg, err_filename)
                raise child_exception_type(err_msg)


        def _handle_exitstatus(self, sts,
                               _waitstatus_to_exitcode=_waitstatus_to_exitcode,
                               _WIFSTOPPED=_WIFSTOPPED,
                               _WSTOPSIG=_WSTOPSIG):
            
            
            
            if _WIFSTOPPED(sts):
                self.returncode = -_WSTOPSIG(sts)
            else:
                self.returncode = _waitstatus_to_exitcode(sts)

        def _internal_poll(self, _deadstate=None, _waitpid=_waitpid,
                _WNOHANG=_WNOHANG, _ECHILD=errno.ECHILD):
            
            if self.returncode is None:
                if not self._waitpid_lock.acquire(False):
                    
                    
                    return None
                try:
                    if self.returncode is not None:
                        return self.returncode  
                    pid, sts = _waitpid(self.pid, _WNOHANG)
                    if pid == self.pid:
                        self._handle_exitstatus(sts)
                except OSError as e:
                    if _deadstate is not None:
                        self.returncode = _deadstate
                    elif e.errno == _ECHILD:
                        
                        
                        
                        
                        
                        self.returncode = 0
                finally:
                    self._waitpid_lock.release()
            return self.returncode


        def _try_wait(self, wait_flags):
            
            try:
                (pid, sts) = os.waitpid(self.pid, wait_flags)
            except ChildProcessError:
                
                
                
                pid = self.pid
                sts = 0
            return (pid, sts)


        def _wait(self, timeout):
            
            if self.returncode is not None:
                return self.returncode

            if timeout is not None:
                endtime = _time() + timeout
                
                
                delay = 0.0005 
                while True:
                    if self._waitpid_lock.acquire(False):
                        try:
                            if self.returncode is not None:
                                break  
                            (pid, sts) = self._try_wait(os.WNOHANG)
                            assert pid == self.pid or pid == 0
                            if pid == self.pid:
                                self._handle_exitstatus(sts)
                                break
                        finally:
                            self._waitpid_lock.release()
                    remaining = self._remaining_time(endtime)
                    if remaining <= 0:
                        raise TimeoutExpired(self.args, timeout)
                    delay = min(delay * 2, remaining, .05)
                    time.sleep(delay)
            else:
                while self.returncode is None:
                    with self._waitpid_lock:
                        if self.returncode is not None:
                            break  
                        (pid, sts) = self._try_wait(0)
                        
                        
                        
                        if pid == self.pid:
                            self._handle_exitstatus(sts)
            return self.returncode


        def _communicate(self, input, endtime, orig_timeout):
            if self.stdin and not self._communication_started:
                
                
                try:
                    self.stdin.flush()
                except BrokenPipeError:
                    pass  
                if not input:
                    try:
                        self.stdin.close()
                    except BrokenPipeError:
                        pass  

            stdout = None
            stderr = None

            
            if not self._communication_started:
                self._fileobj2output = {}
                if self.stdout:
                    self._fileobj2output[self.stdout] = []
                if self.stderr:
                    self._fileobj2output[self.stderr] = []

            if self.stdout:
                stdout = self._fileobj2output[self.stdout]
            if self.stderr:
                stderr = self._fileobj2output[self.stderr]

            self._save_input(input)

            if self._input:
                input_view = memoryview(self._input)

            with _PopenSelector() as selector:
                if self.stdin and input:
                    selector.register(self.stdin, selectors.EVENT_WRITE)
                if self.stdout and not self.stdout.closed:
                    selector.register(self.stdout, selectors.EVENT_READ)
                if self.stderr and not self.stderr.closed:
                    selector.register(self.stderr, selectors.EVENT_READ)

                while selector.get_map():
                    timeout = self._remaining_time(endtime)
                    if timeout is not None and timeout < 0:
                        self._check_timeout(endtime, orig_timeout,
                                            stdout, stderr,
                                            skip_check_and_raise=True)
                        raise RuntimeError(  
                            '_check_timeout(..., skip_check_and_raise=True) '
                            'failed to raise TimeoutExpired.')

                    ready = selector.select(timeout)
                    self._check_timeout(endtime, orig_timeout, stdout, stderr)

                    
                    

                    for key, events in ready:
                        if key.fileobj is self.stdin:
                            chunk = input_view[self._input_offset :
                                               self._input_offset + _PIPE_BUF]
                            try:
                                self._input_offset += os.write(key.fd, chunk)
                            except BrokenPipeError:
                                selector.unregister(key.fileobj)
                                key.fileobj.close()
                            else:
                                if self._input_offset >= len(self._input):
                                    selector.unregister(key.fileobj)
                                    key.fileobj.close()
                        elif key.fileobj in (self.stdout, self.stderr):
                            data = os.read(key.fd, 32768)
                            if not data:
                                selector.unregister(key.fileobj)
                                key.fileobj.close()
                            self._fileobj2output[key.fileobj].append(data)

            self.wait(timeout=self._remaining_time(endtime))

            
            if stdout is not None:
                stdout = b''.join(stdout)
            if stderr is not None:
                stderr = b''.join(stderr)

            
            
            if self.text_mode:
                if stdout is not None:
                    stdout = self._translate_newlines(stdout,
                                                      self.stdout.encoding,
                                                      self.stdout.errors)
                if stderr is not None:
                    stderr = self._translate_newlines(stderr,
                                                      self.stderr.encoding,
                                                      self.stderr.errors)

            return (stdout, stderr)


        def _save_input(self, input):
            
            
            
            if self.stdin and self._input is None:
                self._input_offset = 0
                self._input = input
                if input is not None and self.text_mode:
                    self._input = self._input.encode(self.stdin.encoding,
                                                     self.stdin.errors)


        def send_signal(self, sig):
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            self.poll()
            if self.returncode is not None:
                
                return

            
            
            
            try:
                os.kill(self.pid, sig)
            except ProcessLookupError:
                
                pass

        def terminate(self):
            
            self.send_signal(signal.SIGTERM)

        def kill(self):
            
            self.send_signal(signal.SIGKILL)