2727
2828class Popen(args, bufsize=0, executable=None,
2929 stdin=None, stdout=None, stderr=None,
30- preexec_fn=None, close_fds=_PLATFORM_DEFAULT , shell=False,
30+ preexec_fn=None, close_fds=True , shell=False,
3131 cwd=None, env=None, universal_newlines=False,
3232 startupinfo=None, creationflags=0,
33- restore_signals=True, start_new_session=False):
33+ restore_signals=True, start_new_session=False, pass_fds=() ):
3434
3535
3636Arguments are:
@@ -81,8 +81,11 @@ class Popen(args, bufsize=0, executable=None,
8181
8282If close_fds is true, all file descriptors except 0, 1 and 2 will be
8383closed before the child process is executed. The default for close_fds
84- varies by platform: False on Windows and True on all other platforms
85- such as POSIX.
84+ varies by platform: Always true on POSIX. True when stdin/stdout/stderr
85+ are None on Windows, false otherwise.
86+
87+ pass_fds is an optional sequence of file descriptors to keep open between the
88+ parent and child. Providing any pass_fds implicitly sets close_fds to true.
8689
8790if shell is true, the specified command will be executed through the
8891shell.
@@ -621,17 +624,14 @@ def getoutput(cmd):
621624 return getstatusoutput (cmd )[1 ]
622625
623626
624- if mswindows :
625- _PLATFORM_DEFAULT = False
626- else :
627- _PLATFORM_DEFAULT = True
627+ _PLATFORM_DEFAULT_CLOSE_FDS = object ()
628628
629629
630630class Popen (object ):
631631 def __init__ (self , args , bufsize = 0 , executable = None ,
632632 stdin = None , stdout = None , stderr = None ,
633- preexec_fn = None , close_fds = _PLATFORM_DEFAULT , shell = False ,
634- cwd = None , env = None , universal_newlines = False ,
633+ preexec_fn = None , close_fds = _PLATFORM_DEFAULT_CLOSE_FDS ,
634+ shell = False , cwd = None , env = None , universal_newlines = False ,
635635 startupinfo = None , creationflags = 0 ,
636636 restore_signals = True , start_new_session = False ,
637637 pass_fds = ()):
@@ -648,22 +648,31 @@ def __init__(self, args, bufsize=0, executable=None,
648648 if preexec_fn is not None :
649649 raise ValueError ("preexec_fn is not supported on Windows "
650650 "platforms" )
651- if close_fds and (stdin is not None or stdout is not None or
652- stderr is not None ):
653- raise ValueError ("close_fds is not supported on Windows "
654- "platforms if you redirect stdin/stdout/stderr" )
651+ any_stdio_set = (stdin is not None or stdout is not None or
652+ stderr is not None )
653+ if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS :
654+ if any_stdio_set :
655+ close_fds = False
656+ else :
657+ close_fds = True
658+ elif close_fds and any_stdio_set :
659+ raise ValueError (
660+ "close_fds is not supported on Windows platforms"
661+ " if you redirect stdin/stdout/stderr" )
655662 else :
656663 # POSIX
664+ if close_fds is _PLATFORM_DEFAULT_CLOSE_FDS :
665+ close_fds = True
666+ if pass_fds and not close_fds :
667+ warnings .warn ("pass_fds overriding close_fds." , RuntimeWarning )
668+ close_fds = True
657669 if startupinfo is not None :
658670 raise ValueError ("startupinfo is only supported on Windows "
659671 "platforms" )
660672 if creationflags != 0 :
661673 raise ValueError ("creationflags is only supported on Windows "
662674 "platforms" )
663675
664- if pass_fds and not close_fds :
665- raise ValueError ("pass_fds requires close_fds=True." )
666-
667676 self .stdin = None
668677 self .stdout = None
669678 self .stderr = None
@@ -876,7 +885,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
876885 unused_restore_signals , unused_start_new_session ):
877886 """Execute program (MS Windows version)"""
878887
879- assert not pass_fds , "pass_fds not yet supported on Windows"
888+ assert not pass_fds , "pass_fds not supported on Windows. "
880889
881890 if not isinstance (args , str ):
882891 args = list2cmdline (args )
@@ -1091,7 +1100,7 @@ def _close_all_but_a_sorted_few_fds(self, fds_to_keep):
10911100 # precondition: fds_to_keep must be sorted and unique
10921101 start_fd = 3
10931102 for fd in fds_to_keep :
1094- if fd > start_fd :
1103+ if fd >= start_fd :
10951104 os .closerange (start_fd , fd )
10961105 start_fd = fd + 1
10971106 if start_fd <= MAXFD :
0 commit comments