Index: Doc/library/os.rst =================================================================== --- Doc/library/os.rst (revision 59730) +++ Doc/library/os.rst (working copy) @@ -502,7 +502,19 @@ object" returned by the built-in function :func:`open` or by :func:`popen` or :func:`fdopen`, use its :meth:`close` method. +.. function:: closerange(fd_low, fd_high) + Closes all file descriptors from *fd_low* (inclusive) to *fd_high* (exclusive), + ignoring errors. Availability: Macintosh, Unix, Windows. Equivalent to:: + + for fd in xrange(fd_low, fd_high): + try: + os.close(fd) + except OSError: + pass + + .. versionadded:: 2.6 + .. function:: dup(fd) Return a duplicate of file descriptor *fd*. Availability: Macintosh, Unix, Index: Lib/test/test_os.py =================================================================== --- Lib/test/test_os.py (revision 59730) +++ Lib/test/test_os.py (working copy) @@ -23,6 +23,10 @@ os.close(f) self.assert_(os.access(test_support.TESTFN, os.W_OK)) + def test_closerange(self): + f = os.open(test_support.TESTFN, os.O_CREAT|os.O_RDWR) + # close a fd that is open, and one that isn't + os.closerange(f, f+2) class TemporaryFileTests(unittest.TestCase): def setUp(self): Index: Lib/subprocess.py =================================================================== --- Lib/subprocess.py (revision 59730) +++ Lib/subprocess.py (working copy) @@ -965,15 +965,9 @@ def _close_fds(self, but): - for i in xrange(3, MAXFD): - if i == but: - continue - try: - os.close(i) - except: - pass + os.closerange(3, but) + os.closerange(but + 1, MAXFD) - def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 59730) +++ Modules/posixmodule.c (working copy) @@ -6156,6 +6156,25 @@ } +PyDoc_STRVAR(posix_closerange__doc__, +"closerange(fd_low, fd_high)\n\n\ +Closes all file descriptors in [fd_low, fd_high), ignoring errors."); + +static PyObject * +posix_closerange(PyObject *self, PyObject *args) +{ + int fd_from, fd_to, i; + if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to)) + return NULL; + Py_BEGIN_ALLOW_THREADS + for (i=fd_from; i < fd_to; i++) + close(i); + Py_END_ALLOW_THREADS + Py_INCREF(Py_None); + return Py_None; +} + + PyDoc_STRVAR(posix_dup__doc__, "dup(fd) -> fd2\n\n\ Return a duplicate of a file descriptor."); @@ -8451,6 +8470,7 @@ #endif /* HAVE_TCSETPGRP */ {"open", posix_open, METH_VARARGS, posix_open__doc__}, {"close", posix_close, METH_VARARGS, posix_close__doc__}, + {"closerange", posix_closerange, METH_VARARGS, posix_closerange__doc__}, {"dup", posix_dup, METH_VARARGS, posix_dup__doc__}, {"dup2", posix_dup2, METH_VARARGS, posix_dup2__doc__}, {"lseek", posix_lseek, METH_VARARGS, posix_lseek__doc__},