Path: csiph.com!news.swapon.de!fu-berlin.de!uni-berlin.de!not-for-mail From: Wolfgang Maier Newsgroups: comp.lang.python Subject: Re: Unbuffered stderr in Python 3 Date: Mon, 2 Nov 2015 11:48:32 +0100 Lines: 68 Message-ID: References: <5637165b$0$1505$c3e8da3$5496439d@news.astraweb.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Trace: news.uni-berlin.de w3x8alzVtLX3MXfmKzvYOAmfBCurKftuRPGyfW49GwOw== Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'subject:Python': 0.05; 'rewrite': 0.07; 'sys,': 0.07; 'wrapper': 0.07; 'flush': 0.09; 'lost.': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'stderr': 0.09; 'sys.stderr': 0.09; 'python': 0.10; 'def': 0.13; 'argument': 0.15; '3.3,': 0.16; 'boolean': 0.16; 'buffering': 0.16; 'received:80.91.229.3': 0.16; 'received:io': 0.16; 'received:plane.gmane.org': 0.16; 'received:psf.io': 0.16; 'simulate': 0.16; 'stderr.': 0.16; 'test():': 0.16; 'wrote:': 0.16; '(the': 0.22; 'environments': 0.22; 'function,': 0.22; 'object.': 0.22; 'errors': 0.23; 'import': 0.24; 'header:In-Reply- To:1': 0.24; 'header:User-Agent:1': 0.26; 'example': 0.26; 'header:X-Complaints-To:1': 0.26; 'error': 0.27; 'function': 0.28; 'this.': 0.28; '**kwargs)': 0.29; '**kwargs):': 0.29; 'accepts': 0.29; 'prints': 0.29; 'print': 0.30; "i'd": 0.31; 'usually': 0.33; "d'aprano": 0.33; 'lets': 0.33; 'steven': 0.33; 'file': 0.34; 'best,': 0.35; 'question,': 0.35; 'comment': 0.35; 'but': 0.36; 'should': 0.36; 'instead': 0.36; 'needed': 0.36; 'possible': 0.36; '(and': 0.36; 'keyword': 0.36; 'to:addr:python-list': 0.36; 'subject:: ': 0.37; 'method': 0.37; 'turn': 0.37; 'received:org': 0.37; 'application': 0.39; 'to:addr:python.org': 0.40; 'still': 0.40; 'received:de': 0.40; 'your': 0.60; 'more': 0.63; 'importantly,': 0.66; 'of:': 0.66; 'received:93': 0.72; 'as:': 0.79; 'writing.': 0.84; 'killed': 0.91 X-Injected-Via-Gmane: http://gmane.org/ X-Gmane-NNTP-Posting-Host: x5d86a1a0.dyn.telefonica.de User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 In-Reply-To: <5637165b$0$1505$c3e8da3$5496439d@news.astraweb.com> X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Xref: csiph.com comp.lang.python:98093 On 02.11.2015 08:52, Steven D'Aprano wrote: > In Python 2, stderr is unbuffered. > > In most other environments (the shell, C...) stderr is unbuffered. > > It is usually considered a bad, bad thing for stderr to be buffered. What > happens if your application is killed before the buffer fills up? The errors > in the buffer will be lost. > > So how come Python 3 has line buffered stderr? And more importantly, how can > I turn buffering off? > I cannot comment on your first question, but unbuffered writing to sys.stderr is possible just like for any other buffered file object. You just call its flush method after writing. Since Python3.3, the print function has a flush keyword argument that accepts a boolean and lets you do just this. Rewrite your example as: import sys, time def test(): # Simulate a slow calculation that prints status and/or error # messages to stderr. for i in range(10): _print(i, file=sys.stderr, end="", flush=True) time.sleep(2) print("", file=sys.stderr) and it should do what you want. Before Python 3.3, if I needed an unbuffered print function, I used a wrapper to call flush for me, so instead of: > > import sys, time > > def test(): > # Simulate a slow calculation that prints status and/or error > # messages to stderr. > for i in range(10): > print(i, file=sys.stderr, end="") > time.sleep(2) > print("", file=sys.stderr) > I'd use (and still do this if I need compatibility with 3.2): import sys, time def _print (*args, **kwargs): file = kwargs.get('file', sys.stdout) print(*args, **kwargs) file.flush() def test(): # Simulate a slow calculation that prints status and/or error # messages to stderr. for i in range(10): _print(i, file=sys.stderr, end="") time.sleep(2) print("", file=sys.stderr) Best, Wolfgang