8

A test file named == a.py ==

import os

if __name__ == '__main__':
    for x in range(0,1000):
        try:
            os.sys.stdout.buffer.write(b"hello\r\n")
            os.sys.stdout.buffer.flush()
        except OSError:
            pass

It is ok when it runs alone. But there is problem in following case:

  1. Run python a.py | more
  2. Press ctrl+c to exit

Then I got Exception OSError: OSError(22, 'Invalid argument') in <_io.TextIOWrapper name='' mode='w' encoding='cp936'> ignored

I have catch the OSError already around the os.sys.stdout.buffer operations, but it still goes wrong.

If i don't use os.sys.stdout.buffer.flush, then there's no error message. If I just use print(), everything is OK.

So how to write bytes to the stdout correctly?

I am using Windows 7 64 bit and Python 3.3.0 32 bit.

Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
truease.com
  • 1,261
  • 2
  • 17
  • 30

1 Answers1

13

You can use os.fdopen to reopen stdout with different mode. You can get the file number for stdout with sys.stdout.fileno().

Example:

>>> fp = os.fdopen(sys.stdout.fileno(), 'wb')
>>> fp.write(b'Hello, world')
12
>>> sys.stdout.mode
'w'
>>> fp.mode
'wb'
>>> fp.flush()
Hello, world>>> 
Crowman
  • 25,242
  • 5
  • 48
  • 56
  • It's interesting to notice that this works fine both for python 2 and 3. – Yajo Dec 18 '18 at 12:37
  • You should add `closefd=False` if using `os.fdopen()` as a context manager, to avoid it closing the `sys.stderr` file and then not being able to print errors from there onwards in your script. – Yajo Dec 19 '18 at 12:22