First of all, self.stdout is an instance of django.core.management.base.OutputWrapper command. Its write expects an str, not bytes, thus you can use
self.stdout.write('hello ', ending='')
self.stdout.write('world')
Actually self.stdout.write does accept bytes but only whenever the ending is an empty string - that's because its write method is defined
def write(self, msg, style_func=None, ending=None):
ending = self.ending if ending is None else ending
if ending and not msg.endswith(ending):
msg += ending
style_func = style_func or self.style_func
self._out.write(force_str(style_func(msg)))
If ending is true, then msg.endswith(ending) will fail if msg is a bytes instance and ending is a str.
Furthermore, print with self.stdout does work correctly when I set the self.stdout.ending = '' explicitly; however doing this might mean that other code that uses self.stdout.write expecting it to insert newlines, would fail.
In your case, what I'd do is to define a print method for the Command:
from django.core.management.base import OutputWrapper
class PrintHelper:
def __init__(self, wrapped):
self.wrapped = wrapped
def write(self, s):
if isinstance(self.wrapped, OutputWrapper):
self.wrapped.write(s, ending='')
else:
self.wrapped.write(s)
class Command(BaseCommand):
def print(self, *args, file=None, **kwargs):
if file is None:
file = self.stdout
print(*args, file=PrintHelper(file), **kwargs)
def handle(self, *args, **options):
self.print('hello ', end='')
self.print('world')
You can make this into your own BaseCommand subclass - and you can use it with different files too:
def handle(self, *args, **options):
for c in '|/-\\' * 100:
self.print('\rhello world: ' + c, end='', file=self.stderr)
time.sleep(0.1)
self.print('\bOK')