Issue #7111: Python can now be run without a stdin, stdout or stderr stream.
It was already the case with Python 2. However, the corresponding sys module entries are now set to None (instead of an unusable file object).
This commit is contained in:
commit
39a73a4cfa
|
@ -285,6 +285,45 @@ class CmdLineTest(unittest.TestCase):
|
|||
rc, out, err = assert_python_ok('-c', code)
|
||||
self.assertEqual(b'', err)
|
||||
|
||||
# Issue #7111: Python should work without standard streams
|
||||
|
||||
@unittest.skipIf(os.name != 'posix', "test needs POSIX semantics")
|
||||
def _test_no_stdio(self, streams):
|
||||
code = """if 1:
|
||||
import os, sys
|
||||
for i, s in enumerate({streams}):
|
||||
if getattr(sys, s) is not None:
|
||||
os._exit(i + 1)
|
||||
os._exit(42)""".format(streams=streams)
|
||||
def preexec():
|
||||
if 'stdin' in streams:
|
||||
os.close(0)
|
||||
if 'stdout' in streams:
|
||||
os.close(1)
|
||||
if 'stderr' in streams:
|
||||
os.close(2)
|
||||
p = subprocess.Popen(
|
||||
[sys.executable, "-E", "-c", code],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
preexec_fn=preexec)
|
||||
out, err = p.communicate()
|
||||
self.assertEqual(test.support.strip_python_stderr(err), b'')
|
||||
self.assertEqual(p.returncode, 42)
|
||||
|
||||
def test_no_stdin(self):
|
||||
self._test_no_stdio(['stdin'])
|
||||
|
||||
def test_no_stdout(self):
|
||||
self._test_no_stdio(['stdout'])
|
||||
|
||||
def test_no_stderr(self):
|
||||
self._test_no_stdio(['stderr'])
|
||||
|
||||
def test_no_std_streams(self):
|
||||
self._test_no_stdio(['stdin', 'stdout', 'stderr'])
|
||||
|
||||
|
||||
def test_main():
|
||||
test.support.run_unittest(CmdLineTest)
|
||||
|
|
|
@ -10,6 +10,10 @@ What's New in Python 3.3 Alpha 1?
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Issue #7111: Python can now be run without a stdin, stdout or stderr
|
||||
stream. It was already the case with Python 2. However, the corresponding
|
||||
sys module entries are now set to None (instead of an unusable file object).
|
||||
|
||||
- Issue #11849: Ensure that free()d memory arenas are really released
|
||||
on POSIX systems supporting anonymous memory mappings. Patch by
|
||||
Charles-François Natali.
|
||||
|
|
|
@ -912,6 +912,19 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
is_valid_fd(int fd)
|
||||
{
|
||||
int dummy_fd;
|
||||
if (fd < 0 || !_PyVerify_fd(fd))
|
||||
return 0;
|
||||
dummy_fd = dup(fd);
|
||||
if (dummy_fd < 0)
|
||||
return 0;
|
||||
close(dummy_fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize sys.stdin, stdout, stderr and builtins.open */
|
||||
static int
|
||||
initstdio(void)
|
||||
|
@ -971,13 +984,9 @@ initstdio(void)
|
|||
* and fileno() may point to an invalid file descriptor. For example
|
||||
* GUI apps don't have valid standard streams by default.
|
||||
*/
|
||||
if (fd < 0) {
|
||||
#ifdef MS_WINDOWS
|
||||
if (!is_valid_fd(fd)) {
|
||||
std = Py_None;
|
||||
Py_INCREF(std);
|
||||
#else
|
||||
goto error;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors);
|
||||
|
@ -990,13 +999,9 @@ initstdio(void)
|
|||
|
||||
/* Set sys.stdout */
|
||||
fd = fileno(stdout);
|
||||
if (fd < 0) {
|
||||
#ifdef MS_WINDOWS
|
||||
if (!is_valid_fd(fd)) {
|
||||
std = Py_None;
|
||||
Py_INCREF(std);
|
||||
#else
|
||||
goto error;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors);
|
||||
|
@ -1010,13 +1015,9 @@ initstdio(void)
|
|||
#if 1 /* Disable this if you have trouble debugging bootstrap stuff */
|
||||
/* Set sys.stderr, replaces the preliminary stderr */
|
||||
fd = fileno(stderr);
|
||||
if (fd < 0) {
|
||||
#ifdef MS_WINDOWS
|
||||
if (!is_valid_fd(fd)) {
|
||||
std = Py_None;
|
||||
Py_INCREF(std);
|
||||
#else
|
||||
goto error;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace");
|
||||
|
|
Loading…
Reference in New Issue