Python 2.x - 将二进制输出写入stdout?

时间:2010-03-03 19:47:41

标签: python binary stdout

有没有办法在Python 2.x中将二进制输出写入sys.stdout?在Python 3.x中,您可以使用sys.stdout.buffer(或分离stdout等等),但我无法找到任何Python 2.5 / 2.6的解决方案。

编辑,解决方案: 来自ChristopheD的链接,如下:

import sys

if sys.platform == "win32":
    import os, msvcrt
    msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
编辑:我正在尝试将PDF文件(以二进制形式)推送到stdout以便在Web服务器上提供服务。当我尝试使用sys.stdout.write编写文件时,它会将各种回车符添加到二进制流中,导致PDF呈现损坏。

编辑2:不幸的是,对于这个项目,我需要在Windows服务器上运行,因此Linux解决方案已经完成。

Simply Dummy示例(从磁盘上的文件读取,而不是动态生成,只是因为我们知道生成代码不是问题):

file = open('C:\\test.pdf','rb') 
pdfFile = file.read() 
sys.stdout.write(pdfFile)

5 个答案:

答案 0 :(得分:28)

你在哪个平台?

如果您使用的是Windows,则可以尝试使用this recipe(链接表明它是Windows特定的)。

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

网上有一些参考资料,在Python 3.1中有/应该是一个函数以二进制模式重新打开sys.stdout但是我真的不知道是否有比Python 2更好的替代方案。 X

答案 1 :(得分:8)

您可以使用无缓冲模式:python -u script.py

-u     Force  stdin,  stdout  and stderr to be totally unbuffered.
       On systems where it matters, also put stdin, stdout and stderr
       in binary mode.

答案 2 :(得分:6)

在Python 2.x中,默认情况下所有字符串都是二进制字符数组,所以我相信你应该只能

>>> sys.stdout.write(data)
编辑:我已经证实了你的经历。

我创建了一个文件gen_bytes.py

import sys
for char in range(256):
    sys.stdout.write(chr(char))

另一个read_bytes.py

import subprocess
import sys

proc = subprocess.Popen([sys.executable, 'gen_bytes.py'], stdout=subprocess.PIPE)
res = proc.wait()
bytes = proc.stdout.read()
if not len(bytes) == 256:
    print 'Received incorrect number of bytes: {0}'.format(len(bytes))
    raise SystemExit(1)
if not map(ord, bytes) == range(256):
    print 'Received incorrect bytes: {0}'.format(map(ord, bytes))
    raise SystemExit(2)
print "Everything checks out"

将它们放在同一目录中并运行read_bytes.py。果然,似乎Python实际上是在输出上转换换行符。我怀疑这只发生在Windows操作系统上。

> .\read_bytes.py
Received incorrect number of bytes: 257

在ChristopheD的带领下,将gen_bytes更改为以下内容可以解决问题。

import sys

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

for char in range(256):
    sys.stdout.write(chr(char))

我将此包含在内是为了完整性。 ChristopheD值得称赞。

答案 3 :(得分:5)

您可以使用argopen。argopen(),它将dash作为stdin / stdout处理,并修复Windows上的二进制模式。

import argopen
stdout = argopen.argopen('-', 'wb')
stdout.write(some_binary_data)

答案 4 :(得分:0)

我使用文件描述符的包装器解决了这个问题。 (在Cygwin的Python 3.2.5中测试)

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