You can define a local function called _print
(or even override the system print
function by naming it print
) as follows:
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')
The output should be AB
.
Note: normally the system print
function adds a newline to the output. The above _print
just outputs the data (either bytes
or by assuming it's str
) without the newline.
buffered implementation
If you want buffered I/O, you can manage that by using the tools from the io
library.
Simple example:
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()
If you are performing all the output writes in a function, for example, you can use the contextlib.contextmanager
to create a factory function that allow you to use the with ...
statement:
# 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")
See: