如何在python 3中将二进制数据写入stdout?


103

在python 2.x中,我可以这样做:

import sys, array
a = array.array('B', range(100))
a.tofile(sys.stdout)

但是现在,我得到了TypeError: can't write bytes to text stream。我应该使用一些秘密编码吗?


4
这将是更好的找到一个答案,将与Python 2.6+和3.x工作
索林

2
os.write将同时在Py2和Py3上运行。
David Wolever

Answers:


169

更好的方法:

import sys
sys.stdout.buffer.write(b"some binary data")

4
使用即使在源文件对象提供字节而不是字符串的情况下sys.stdout.buffer,您也可以执行使用shutil.copyfileobj操作。+1
csl

1
使用此程序的程序无法在IDLE 3中进行测试:AttributeError: 'PseudoOutputFile' object has no attribute 'buffer'
Damian Yerrick

4
IDLE中的@DamianYerrick(至少在Windows中)pythonw.exe运行IDLE,这意味着没有stdout。它是用tkinter模拟的。它实际上无法处理字节。在这种情况下,.decode('UTF-8', errors='replace')请输入您的字符串,或者运行python3 -I <filename>以获取REPL而不是使用IDLE。
Artyer

stderr如果与结合使用,则会在写入时显示写入顺序print(file=sys.stderr)
Kotauskas

15
import os
os.write(1, a.tostring())

或者,os.write(sys.stdout.fileno(), …)如果这比1您可读性强。


谢谢,那行得通。感觉有点乱,但我想这并不是一件普通的事情。
伊万·巴尔丁

6
问题os.write在于您必须检查返回值,因为它不能保证所有内容都会被写入。
mic_e 2015年

10

只能在Python 3中使用的惯用方式是:

with os.fdopen(sys.stdout.fileno(), "wb", closefd=False) as stdout:
    stdout.write(b"my bytes object")
    stdout.flush()

好地方是它使用普通的文件对象接口,每个人都在Python中使用它。

请注意,我正在设置closefd=False为避免sys.stdout退出with块时关闭。否则,您的程序将无法再打印到标准输出。但是,对于其他类型的文件描述符,您可能要跳过该部分。


你为什么要冲洗?让Python决定何时刷新标准输出不是更好吗?
马丁

0

如果您想在python3中指定编码,则仍然可以使用bytes命令,如下所示:

import os
os.write(1,bytes('Your string to Stdout','UTF-8'))

其中1是stdout的对应常规编号-> sys.stdout.fileno()

否则,如果您不关心编码,请使用:

import sys
sys.stdout.write("Your string to Stdout\n")

如果要使用不带编码的os.write,请尝试使用以下内容:

import os
os.write(1,b"Your string to Stdout\n")

1
使用的程序os.write(sys.stdout.fileno(), some_bytes)在IDLE中不起作用。io.UnsupportedOperation: fileno
Damian Yerrick '17

@DamianYerrick:你是对的……无论如何都不应使用IDLE来测试类似的东西。简短地说:尝试打开IDLE(我有python3.5.1外壳),然后简单地导入sys和sys.stdout.fileno(),它将抛出io错误,因为在IDLE中不支持此操作:-)始终很重要记住您在哪种环境下工作并尝试获得可能的一切;)希望这可以澄清您的查询:-)周末愉快。
Marco smdm

您只提到了一种将实际二进制数据写入的方法stdout,最后一种。
Kotauskas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.