classification
Title: print in pythonw raises silent exception when no console available
Type: behavior Stage: resolved
Components: IO, Windows Versions: Python 2.7, Python 2.6
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: mhammond Nosy List: BreamoreBoy, alanjds, amaury.forgeotdarc, amiseler, christian.heimes, georg.brandl, jcea, mhammond, pysquared, santoso.wijaya, techtonik, tim.peters, tim_evans
Priority: normal Keywords:

Created on 2003-03-19 13:05 by amiseler, last changed 2013-10-13 18:13 by georg.brandl. This issue is now closed.

Messages (22)
msg15196 - (view) Author: Alexander Miseler (amiseler) Date: 2003-03-19 13:05
platform: win2k
testet with: 2.2.2   2.3a1   2.3a2

the test case works fine when the script is run with
python.exe. with pythonw.exe an exception is raised
after printing 4096 bytes. the exception is rather
obscure but the bytecount suggests a buffer overflow.

print (or to be more exact sys.stdout.write) should be
a noop when there is no console.


test case:
import traceback
counter = 0
try:
	for counter in range(100000):
		print 'a',
	success_file = open('success.txt', 'w')
	success_file.write('Bytes printed: %d\n' % (counter*2))
	success_file.close()
except:
	error_file = open('error.txt', 'w')
	error_file.write('Bytes printed before exception was
raised: %d\n' % (counter*2))
	traceback.print_exc(100, error_file)
	error_file.close()


output:
Bytes printed before exception was raised: 4096
Traceback (most recent call last):
  File "test_case.py", line 5, in ?
    print 'a',
IOError: [Errno 9] Bad file descriptor
msg15197 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2003-03-19 17:18
Logged In: YES 
user_id=31435

Mark, give a rip <wink>?
msg15198 - (view) Author: Mark Hammond (mhammond) * (Python committer) Date: 2003-03-19 23:51
Logged In: YES 
user_id=14198

I struck this years ago, but was in a quandry.  On one hand,
sys.stdout *is* invalid, and I see no reason why Python
should mask these errors.  There may be real applications
where this failure *must* be reported to the program rather
than simply consumed.

However, I see the point that print is so basic that is
should never fail.  To my mind, the first point outweighs
the first, and the problem is fairly simply solved (see if
sys.stdout is invalid, and if so, open a file and set it to
that).

So I am afraid that, no, I don't give a rats <wink>.  Unless
conivenced otherwise (ie, by Tim or Guido) I will close this
as "not a bug" in a week or so.
msg15199 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2003-03-20 04:17
Logged In: YES 
user_id=31435

I can swing either way on this, or even a third:  open text 
files stdout.txt and stderr.txt in the current directory then.  
That's really aiming at a different irritation, though, that 
tracebacks end up in the bit bucket by default under 
pythonw.

BTW, making stdout and stderr /dev/null workalikes is 
least attractive to me (nobody would write to stdout or 
stderr *intending* the output be lost).  I'm (barely) OK with 
letting it stay as it is, because that just reflects Windows 
reality.
msg15200 - (view) Author: Alexander Miseler (amiseler) Date: 2003-03-20 09:19
Logged In: YES 
user_id=693638

then please throw a meaningful exception at first byte
written, not an obscure exception after 4096 bytes written.
msg15201 - (view) Author: Alexander Miseler (amiseler) Date: 2003-03-20 13:40
Logged In: YES 
user_id=693638

and to say something FOR noop:
tim_one: "(nobody would write to stdout or stderr
*intending* the output be lost)"

yes, but someone would use print in an application and still
intend this application to run on any platform supported by
python.
its not really intuitive for someone programming under linux
that the print statement may limit the portability.

btw: the microsoft implementations (visual studio) of printf
and cout seem to be noops for non-console applications.
no idea how other windows compilers (mingw?) handle this.

i would consider it best, to make sys.stdout.write a noop
but to provide some other means to inquire the availability
of text output.
msg15202 - (view) Author: Graham Horler (pysquared) Date: 2003-03-26 13:59
Logged In: YES 
user_id=543663

I just submitted a bug report ([ 710041 ] sys.stdout IOError 
under Windows) with this same problem, so I closed it and will 
add some of my comments here, in the hopes they will be 
useful:

Python 2.1.2 (#31, Jan 15 2002, 17:28:11) [MSC 32 bit 
(Intel)] on win32.
Under Windoze 98, in a non-console application.

Calls to the write() methods seem to discard  the data, which 
is what I want (when running a cross-platform GUI program 
with debug print statements).

BUT, when the write() method is called with more than 
about 4KB, it raises "IOError: [Errno 9] Bad file descriptor", 
the same as if you had manually called the flush() method.

This IOError happens when write()ing even one character 
if "pythonw.exe -u" was used to start the GUI.

I work around it by defining my own bit-bucket for 
sys.std[out|err].
(NOTE: This bug was hard to track down!)
msg15203 - (view) Author: Tim Evans (tim_evans) Date: 2003-04-11 00:49
Logged In: YES 
user_id=561705

Yet another alternative: when soneone writes to stdout or
stderr, open a console window and write into that.  I have
seen this used by the win32 vesion of Glade (the GTK gui
builder), so it may be a part of the win32 version of GTK or
Glib.

Personally, I would prefer just discarding the output.  This
is not inconsistant.  My gui apps on Linux are started from
the gnome panel (or an equivalent), not an xterm, so
anything they print gets discarded too.

Note that it is still posible to capture the stdout and
stderr of pythonw (at least on NT/2K/XP) by redirecting them
at the command prompt, like this: pythonw spam.pyw >
stdout.log 2> stderr.log
msg75973 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-11-17 16:25
Python 3.0 already discards the output in this case (see issue1415):
it sets sys.stdout=None and silently ignores prints to the None file.

I think this is the correct behavior, but I'm not sure this can be
backported to 2.7, because of compatibility issues.
msg97442 - (view) Author: Alan Justino (alanjds) Date: 2010-01-08 21:32
FWIW: I don't know if it changes anything, but when deploying Django projects on some clients who uses Windows as server, I'm using this piece of code to workarround this issue:

## Fixes "IOError: [Errno 9] Bad file descriptor" when in pythonw.exe of Windows

if sys.platform.find('win') != -1 and sys.executable.find('pythonw') != -1:

    blackhole = file(os.devnull, 'w')

    sys.stdout = sys.stderr = blackhole

##

Is not my intention to remove print statments neither to send they to a file. For this I'm using logging module.

I really expect they to be silently ignored, bothering not my user.
msg114222 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2010-08-18 14:12
Works fine with pythonw on 2.6 and 2.7.
msg114224 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2010-08-18 14:25
No, nothing changed in this aspect since python 2.2.
With 2.7, I get the same error.txt file containing the "Bad file descriptor" message.
msg114232 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2010-08-18 15:20
@Amaury I tested with Windows Vista and the latest 2.6 and 2.7 maintainance releases, what did you use?
msg114335 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2010-08-19 08:05
I use Windows XP.
Note that nothing is displayed on screen. there is just a error.txt file in the current directory.
msg114359 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2010-08-19 12:55
Ah I was misreading things, I too can confirm that it is still a problem.
msg130660 - (view) Author: Santoso Wijaya (santoso.wijaya) * Date: 2011-03-12 04:06
This is indeed reproducible in Python 2.7. The following unittest will expose it. However, patching sys.std* to None will break `print` statements to raise AttributeError in pythonw.exe programs, though it won't mysteriously break only after printing 4 kbytes...

diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
old mode 100644
new mode 100755
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -58,6 +58,19 @@
         new = sys.getrefcount(path)
         self.assertEqual(old, new)
 
+    @unittest.skipUnless(sys.platform == 'win32',
+                         'test specific to Windows console')
+    def test_print_no_stdout(self):
+        # Issue #706263: pythonw.exe will raise an IOError after
+        # attempting to print more than 4096 bytes (it silently
+        # succeeds for the first 4096 bytes and fails with an
+        # IOError: "[Errno 9] Bad file descriptor" on the 4097th byte.
+        DETACHED_PROCESS = 0x00000008
+        command = [sys.executable, '-c',
+                   'for _ in xrange(100000): print "a", ']
+        retcode = subprocess.call(command, creationflags=DETACHED_PROCESS)
+        self.assertEqual(retcode, 0)
+
 
 class TemporaryFileTests(unittest.TestCase):
     def setUp(self):
msg136238 - (view) Author: Jesús Cea Avión (jcea) * (Python committer) Date: 2011-05-18 12:39
Does this affects Python 3?
msg136240 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2011-05-18 12:42
Python 3 is not affected: pythonw.exe sets sys.stderr to None, and print() silently discards the output in this case.
msg190035 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2013-05-25 23:30
Is it really worth leaving this open?  There's no consensus after ten years and it only impacts on Python 2.7.  Mark Hammond made his view plain in msg15198, which is supported by the fact that a type has yet to be allocated.
msg191901 - (view) Author: anatoly techtonik (techtonik) Date: 2013-06-26 10:34
This is still an issue for Python 2 users. Most important that pythonw.exe has a magic ability to fail silently leaving users with no means to create valid bug reports (the reason why StackOverflow questions are downvoted and erased).

http://bugs.ascend4.org/print_bug_page.php?bug_id=471
stream https://code.google.com/p/spyderlib/issues/detail?id=1260

The argument in msg15198 is somewhat misleading. If pythonw.exe fails because of print statement or because other issue, there is no way to report that.

Anyway, this reminds me very much of mod_wsgi, with only problem that Python developers don't receive as much feedback as Graham to make the change: http://blog.dscpl.com.au/2009/04/wsgi-and-printing-to-standard-output.html
msg191902 - (view) Author: Christian Heimes (christian.heimes) * (Python committer) Date: 2013-06-26 11:11
I recommend against changing the code so late in the Python 2.7 release cycle. A change in behavior is too confusing.
And it's not a bug but a design decision, too. Over five years ago I implement parts of the IO interaction with the operating system for Python 3.0. I deliberately did NOT port modifications to 2.6.

If you want to get Python 3.x style print() behavior in Python 2.7 you can have it already:

from __future__ import print_function
import sys
if sys.executable.endswith("pythonw.exe"):
    sys.stdout = sys.stdout = None

print("can handle sys.stdout = None just fine.")
msg199743 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2013-10-13 18:13
I agree with Christian; closing as suggested.
History
Date User Action Args
2013-10-13 18:13:18georg.brandlsetstatus: pending -> closed
nosy: + georg.brandl
messages: + msg199743

2013-06-26 11:11:41christian.heimessetstatus: open -> pending

type: behavior

nosy: + christian.heimes
messages: + msg191902
resolution: wont fix
stage: resolved
2013-06-26 10:34:56techtoniksetnosy: + techtonik

messages: + msg191901
title: print raises exception when no console available -> print in pythonw raises silent exception when no console available
2013-05-25 23:30:47BreamoreBoysetmessages: + msg190035
2011-05-18 12:42:38amaury.forgeotdarcsetmessages: + msg136240
2011-05-18 12:39:27jceasetnosy: + jcea
messages: + msg136238
2011-03-12 04:06:54santoso.wijayasetnosy: tim.peters, mhammond, pysquared, amaury.forgeotdarc, amiseler, tim_evans, alanjds, santoso.wijaya, BreamoreBoy
messages: + msg130660
2011-03-11 20:32:33santoso.wijayasetnosy: tim.peters, mhammond, pysquared, amaury.forgeotdarc, amiseler, tim_evans, alanjds, santoso.wijaya, BreamoreBoy
components: + IO
2011-03-11 20:32:14santoso.wijayasetnosy: + santoso.wijaya

versions: + Python 2.7
2010-09-10 06:49:24amaury.forgeotdarclinkissue9503 superseder
2010-08-19 12:55:23BreamoreBoysetmessages: + msg114359
2010-08-19 08:05:14amaury.forgeotdarcsetmessages: + msg114335
2010-08-18 15:20:28BreamoreBoysetmessages: + msg114232
2010-08-18 14:25:01amaury.forgeotdarcsetstatus: closed -> open
resolution: out of date -> (no value)
messages: + msg114224
2010-08-18 14:12:21BreamoreBoysetstatus: open -> closed

nosy: + BreamoreBoy
messages: + msg114222

resolution: out of date
2010-01-08 21:32:27alanjdssetnosy: + alanjds

messages: + msg97442
versions: + Python 2.6
2008-11-17 16:25:33amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg75973
2008-11-17 16:23:27amaury.forgeotdarclinkissue973507 superseder
2003-03-19 13:05:43amiselercreate