Python 2.x – 写入二进制输出到标准输出?

有没有办法在Python 2.x中写入二进制输出到sys.stdout? 在Python 3.x中,你可以使用sys.stdout.buffer(或分离标准输出等),但是我一直没有findPython 2.5 / 2.6的解决scheme。

编辑, 解决scheme :从ChristopheD的链接,下面:

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

编辑:我试图推送一个PDF文件(在二进制forms)标准输出在Web服务器上。 当我尝试使用sys.stdout.write写入文件时,会将各种回车符添加到导致PDF渲染损坏的二进制stream中。

编辑2:对于这个项目,我需要运行在Windows服务器,不幸的是,所以Linux的解决scheme。

简单的例子(从磁盘上的文件读取,而不是实时生成,只是为了我们知道代码不是问题):

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

你在哪个平台上?

你可以尝试这个配方,如果你在Windows上(链接暗示它是特定于Windows的)。

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

网上有一些参考文献说,在Python 3.1中应该有一个函数来以二进制模式重新打开sys.stdout ,但是我不知道是否有更好的select,那么上面的Python 2.x.

你可以使用非缓冲模式: python -u script.py

 -u强制stdin,stdout和stderr完全无缓冲。
       在重要的系统上,也把stdin,stdout和stderr
       在二进制模式。

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

 >>> sys.stdout.write(data) 

编辑:我已经证实你的经验。

我创build了一个文件,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值得信任。

您可以使用argopen .argopen(),它将stash / stdout作为破折号处理,并在Windows上修复二进制模式。

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

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

 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