Python 2.x - 将二进制输出写入标准输出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2374427/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python 2.x - Write binary output to stdout?
提问by Eavesdown
Is there any way to write binary output to sys.stdout in Python 2.x? In Python 3.x, you can just use sys.stdout.buffer (or detach stdout, etc...), but I haven't been able to find any solutions for Python 2.5/2.6.
有没有办法在 Python 2.x 中将二进制输出写入 sys.stdout?在 Python 3.x 中,您可以只使用 sys.stdout.buffer (或分离 stdout 等),但我一直无法找到适用于 Python 2.5/2.6 的任何解决方案。
EDIT, Solution: From ChristopheD's link, below:
编辑,解决方案:来自 ChristopheD 的链接,如下:
import sys
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
EDIT: I'm trying to push a PDF file (in binary form) to stdout for serving up on a web server. When I try to write the file using sys.stdout.write, it adds all sorts of carriage returns to the binary stream that causes the PDF to render corrupt.
编辑:我正在尝试将 PDF 文件(以二进制形式)推送到标准输出,以便在 Web 服务器上提供服务。当我尝试使用 sys.stdout.write 编写文件时,它会将各种回车添加到导致 PDF 呈现损坏的二进制流中。
EDIT 2: For this project, I need to run on a Windows Server, unfortunately, so Linux solutions are out.
编辑 2:对于这个项目,不幸的是,我需要在 Windows Server 上运行,所以 Linux 解决方案已经过时了。
Simply Dummy Example (reading from a file on disk, instead of generating on the fly, just so we know that the generation code isn't the issue):
简单的虚拟示例(从磁盘上的文件中读取,而不是动态生成,只是为了让我们知道生成代码不是问题):
file = open('C:\test.pdf','rb')
pdfFile = file.read()
sys.stdout.write(pdfFile)
采纳答案by ChristopheD
Which platform are you on?
你在哪个平台?
You could try this recipeif you're on Windows (the link suggests it's Windows specific anyway).
如果你在 Windows 上,你可以试试这个食谱(链接表明它是特定于 Windows 的)。
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
There are some references on the web that there would/should be a function in Python 3.1 to reopen sys.stdout
in binary mode but I don't really know if there's a better alternative then the above for Python 2.x.
网上有一些参考资料说 Python 3.1 中会有/应该有一个函数可以sys.stdout
在二进制模式下重新打开,但我真的不知道是否有更好的替代方案,而不是上面的 Python 2.x。
回答by Tim Delaney
You can use unbuffered mode: python -u script.py
.
您可以使用无缓冲模式: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.
回答by inv
回答by Jason R. Coombs
In Python 2.x, all strings are binary character arrays by default, so I believe you should be able to just
在 Python 2.x 中,默认情况下所有字符串都是二进制字符数组,所以我相信你应该能够
>>> sys.stdout.write(data)
EDIT: I've confirmed your experience.
编辑:我已经证实了你的经历。
I created one file, gen_bytes.py
我创建了一个文件,gen_bytes.py
import sys
for char in range(256):
sys.stdout.write(chr(char))
And another read_bytes.py
另一个 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"
Put them in the same directory and run read_bytes.py. Sure enough, it appears as if Python is in fact converting newlines on output. I suspect this only happens on a Windows OS.
将它们放在同一目录中并运行 read_bytes.py。果然,看起来好像 Python 实际上正在转换输出中的换行符。我怀疑这只发生在 Windows 操作系统上。
> .\read_bytes.py
Received incorrect number of bytes: 257
Following the lead by ChristopheD, and changing gen_bytes to the following corrects the issue.
在 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))
I include this for completeness. ChristopheD deserves the credit.
我包括这个是为了完整性。ChristopheD 值得称赞。
回答by Niklas R
I solved this using a wrapper for a file-descriptor. (Tested in Python 3.2.5 on Cygwin)
我使用文件描述符的包装器解决了这个问题。(在 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