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')