存在一个问题How to write binary data to stdout in python 3?,但所有答案都建议sys.stdout.buffer
或其变体(例如,手动重新包装文件描述符),但有一个问题:它们不考虑缓冲:< / p>
MacBook-Pro-116:~ ezyang$ cat test.py
import sys
sys.stdout.write("A")
sys.stdout.buffer.write(b"B")
MacBook-Pro-116:~ ezyang$ python3 test.py | cat
BA
是否有一种方法可以在尊重sys.stdout
和未经修饰的print
语句的缓冲的同时将二进制数据写入stdout? (实际的用例是,我有一个未知编码的“类似文本”的数据,我只想直接将其传递给stdout而不承诺使用特定的编码。)
答案 0 :(得分:0)
您可以定义一个名为_print
的局部函数(甚至可以通过命名print
来覆盖系统print
函数),如下所示:
import sys
def _print(data):
"""
If data is bytes, write to stdout using sys.stdout.buffer.write,
otherwise, assume it's str and convert to bytes with utf-8
encoding before writing.
"""
if type(data) != bytes:
data = bytes(data, 'utf-8')
sys.stdout.buffer.write(data)
_print('A')
_print(b'B')
输出应为AB
。
注意:通常,系统print
函数将换行符添加到输出中。上面的_print
仅输出数据(bytes
或假设其为str
)而没有换行符。
如果要缓冲的I / O,可以使用io
库中的工具进行管理。
简单的例子:
import io
import sys
output_buffer = None
text_wrapper = None
def init_buffer():
global output_buffer, text_wrapper
if not output_buffer:
output_buffer = io.BytesIO()
text_wrapper = io.TextIOWrapper(
output_buffer,
encoding='utf-8',
write_through=True)
def write(data):
if type(data) == bytes:
output_buffer.write(data)
else:
text_wrapper.write(data)
def flush():
sys.stdout.buffer.write(output_buffer.getvalue())
# initialize buffer, write some data, and then flush to stdout
init_buffer()
write("A")
write(b"B")
write("foo")
write(b"bar")
flush()
例如,如果要执行某个函数中的所有输出写操作,则可以使用contextlib.contextmanager
创建一个工厂函数,该函数可以使用with ...
语句:
# This uses the vars and functions in the example above.
import contextlib
@contextlib.contextmanager
def buffered_stdout():
"""
Create a factory function for using the `with` statement
to write to the output buffer.
"""
global output_buffer
init_buffer()
fh = sys.stdout.buffer
try:
yield fh
finally:
try:
fh.write(output_buffer.getvalue())
except AttributeError:
pass
# open the buffered output stream and write some data to it
with buffered_stdout():
write("A")
write(b"B")
write("foo")
write(b"bar")
请参阅:
答案 1 :(得分:0)
您不能将对write
的呼叫与flush
进行交错吗?
sys.stdout.write("A")
sys.stdout.buffer.write(b"B")
结果:
BA
sys.stdout.write("A")
sys.stdout.flush()
sys.stdout.buffer.write(b"B")
sys.stdout.flush()
结果:
AB