summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2012-01-13 18:41:25 (GMT)
committerGeorg Brandl <georg@python.org>2012-01-13 18:41:25 (GMT)
commitbc3b682923a22b89b0f5462ee2e807a4cc4ea81d (patch)
treed9842f6dfe5185783fe797d62c2e8e43efdff593
parent5136ac0ca21a05691978df8d0650f902c8ca3463 (diff)
downloadcpython-bc3b682923a22b89b0f5462ee2e807a4cc4ea81d.zip
cpython-bc3b682923a22b89b0f5462ee2e807a4cc4ea81d.tar.gz
cpython-bc3b682923a22b89b0f5462ee2e807a4cc4ea81d.tar.bz2
Closes #13761: add a "flush" keyword argument to print().
-rw-r--r--Doc/library/functions.rst11
-rw-r--r--Lib/test/test_print.py26
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/bltinmodule.c24
4 files changed, 55 insertions, 9 deletions
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index c845283..e4b14b8 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -946,7 +946,7 @@ are always available. They are listed here in alphabetical order.
must be of integer types, and *y* must be non-negative.
-.. function:: print([object, ...], *, sep=' ', end='\\n', file=sys.stdout)
+.. function:: print([object, ...], *, sep=' ', end='\\n', file=sys.stdout, flush=False)
Print *object*\(s) to the stream *file*, separated by *sep* and followed by
*end*. *sep*, *end* and *file*, if present, must be given as keyword
@@ -959,9 +959,12 @@ are always available. They are listed here in alphabetical order.
*end*.
The *file* argument must be an object with a ``write(string)`` method; if it
- is not present or ``None``, :data:`sys.stdout` will be used. Output buffering
- is determined by *file*. Use ``file.flush()`` to ensure, for instance,
- immediate appearance on a screen.
+ is not present or ``None``, :data:`sys.stdout` will be used. Whether output
+ is buffered is usually determined by *file*, but if the *flush* keyword
+ argument is true, the stream is forcibly flushed.
+
+ .. versionchanged:: 3.3
+ Added the *flush* keyword argument.
.. function:: property(fget=None, fset=None, fdel=None, doc=None)
diff --git a/Lib/test/test_print.py b/Lib/test/test_print.py
index 8d37bbc..9d6dbea 100644
--- a/Lib/test/test_print.py
+++ b/Lib/test/test_print.py
@@ -111,6 +111,32 @@ class TestPrint(unittest.TestCase):
self.assertRaises(TypeError, print, '', end=3)
self.assertRaises(AttributeError, print, '', file='')
+ def test_print_flush(self):
+ # operation of the flush flag
+ class filelike():
+ def __init__(self):
+ self.written = ''
+ self.flushed = 0
+ def write(self, str):
+ self.written += str
+ def flush(self):
+ self.flushed += 1
+
+ f = filelike()
+ print(1, file=f, end='', flush=True)
+ print(2, file=f, end='', flush=True)
+ print(3, file=f, flush=False)
+ self.assertEqual(f.written, '123\n')
+ self.assertEqual(f.flushed, 2)
+
+ # ensure exceptions from flush are passed through
+ class noflush():
+ def write(self, str):
+ pass
+ def flush(self):
+ raise RuntimeError
+ self.assertRaises(RuntimeError, print, 1, file=noflush(), flush=True)
+
def test_main():
support.run_unittest(TestPrint)
diff --git a/Misc/NEWS b/Misc/NEWS
index fddf5d4..d3930ed 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1?
Core and Builtins
-----------------
+- Issue #13761: Add a "flush" keyword argument to the print() function,
+ used to ensure flushing the output stream.
+
- Issue #13645: pyc files now contain the size of the corresponding source
code, to avoid timestamp collisions (especially on filesystems with a low
timestamp resolution) when checking for freshness of the bytecode.
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index d1630cc..81402fc 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1484,15 +1484,15 @@ equivalent to (x**y) % z, but may be more efficient (e.g. for longs).");
static PyObject *
builtin_print(PyObject *self, PyObject *args, PyObject *kwds)
{
- static char *kwlist[] = {"sep", "end", "file", 0};
+ static char *kwlist[] = {"sep", "end", "file", "flush", 0};
static PyObject *dummy_args;
- PyObject *sep = NULL, *end = NULL, *file = NULL;
+ PyObject *sep = NULL, *end = NULL, *file = NULL, *flush = NULL;
int i, err;
if (dummy_args == NULL && !(dummy_args = PyTuple_New(0)))
- return NULL;
- if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|OOO:print",
- kwlist, &sep, &end, &file))
+ return NULL;
+ if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|OOOO:print",
+ kwlist, &sep, &end, &file, &flush))
return NULL;
if (file == NULL || file == Py_None) {
file = PySys_GetObject("stdout");
@@ -1543,6 +1543,20 @@ builtin_print(PyObject *self, PyObject *args, PyObject *kwds)
if (err)
return NULL;
+ if (flush != NULL) {
+ PyObject *tmp;
+ int do_flush = PyObject_IsTrue(flush);
+ if (do_flush == -1)
+ return NULL;
+ else if (do_flush) {
+ tmp = PyObject_CallMethod(file, "flush", "");
+ if (tmp == NULL)
+ return NULL;
+ else
+ Py_DECREF(tmp);
+ }
+ }
+
Py_RETURN_NONE;
}