Welcome, guest | Sign In | My Account | Store | Cart

You want to send binary data, such as for an image, to stdout under Windows.

Python, 5 lines
1
2
3
4
5
import sys

if sys.platform == "win32":
    import os, msvcrt
    msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

If you are reading or writing binary data under Windows, such as for an image, then the file must specifically be opened in binary mode (Unix doesn't make a distinction between text and binary modes). But this is a problem for a program that wants to write binary data to standard output (as a web CGI program would be expected to do), since the 'sys' module opens the 'stdout' file object on your behalf and normally does so in text mode. You could have 'sys' open 'stdout' in binary mode instead by supplying the '-u' command-line option to the Python interpreter. But if you want to control this mode from within a program, then (as shown in the code sample) you can use the 'setmode' function provided by the Windows-specific 'msvcrt' module to change the mode of stdout's underlying file descriptor.

2 comments

Niklas 9 years, 5 months ago  # | flag

This works for me, no need for msvcrt (which is not available on Cygwin, but you still get problems)

class BinaryFile(object):
    ''' Wraps a file-descriptor to binary read/write. The wrapped
    file can not be closed by an instance of this class, it must
    happen through the original file object.

    :param fd: A file-descriptor (integer) or file-object that
        supports the ``fileno()`` method. '''

    def __init__(self, fd):
        super(BinaryFile, self).__init__()
        if not isinstance(fd, int):
            fd = fd.fileno()
        self.fd = fd

    def write(self, data):
        if not isinstance(data, bytes):
            raise TypeError('must be bytes, got %s' % type(data).__name__)
        return os.write(self.fd, data)

    def read(self, length=None):
        if length is not None:
            return os.read(self.fd, length)
        else:
            result = b''
            while True:
                data = self.read(1024)
                if not data:
                    break
                result += data
            return result
Niklas 9 years, 5 months ago  # | flag

PS: More extended example.

class BinaryFile(object):
    ''' Wraps a file-descriptor to binary read/write. The wrapped
    file can not be closed by an instance of this class, it must
    happen through the original file.

    :param fd: A file-descriptor (integer) or file-object that
        supports the ``fileno()`` method. '''

    def __init__(self, fd):
        super(BinaryFile, self).__init__()
        fp = None
        if not isinstance(fd, int):
            fp = fd
            fd = fp.fileno()
        self.fd = fd
        self.fp = fp

    def fileno(self):
        return self.fd

    def tell(self):
        if self.fp and hasattr(self.fp, 'tell'):
            return self.fp.tell()
        else:
            raise io.UnsupportedOperation(
                'can not tell position from file-descriptor')

    def seek(self, pos, how=os.SEEK_SET):
        try:
            return os.lseek(self.fd, pos, how)
        except OSError as exc:
            raise io.UnsupportedOperation('file-descriptor is not seekable')

    def write(self, data):
        if not isinstance(data, bytes):
            raise TypeError('must be bytes, got %s' % type(data).__name__)
        return os.write(self.fd, data)

    def read(self, length=None):
        if length is not None:
            return os.read(self.fd, length)
        else:
            result = b''
            while True:
                data = self.read(1024)
                if not data:
                    break
                result += data
            return result