Running Django v1.10 on Python 3.5.0:
from django.core.management.base import BaseCommand
class Command(BaseCommand):
def handle(self, *args, **options):
print('hello ', end='', file=self.stdout)
print('world', file=self.stdout)
Expected output:
hello world
Actual output:
hello
world
How do I correctly pass the ending character? I currently use a workaround of setting explicitly:
self.stdout.ending = ''
But this hack means you don't get all the features of the print function, you must use self.stdout.write
and prepare the bytes manually.
As is mentioned in Django 1.10's Custom Management Commands document:
Hence, in order to print in your
Command
class, you should define yourhandle()
function as:Also, by explicitly setting
self.stdout.ending = ''
, you are modifying the property ofself.stdout
object. But you may not want this to be reflected in future calls ofself.stdout.write()
. Hence it will be better to useending
parameter withinself.stdout.write()
function (as demonstrated in sample code above).As you mentioned "But this hack means you don't get all the features of the print function, you must use self.stdout.write and prepare the bytes manually." No, you do not have to worry about creating the
bytes
or other features ofprint()
, asself.stdout.write()
function belonging toOutputWrapper
class expects data to be instr
format. Also I would like to mention thatprint()
andOutputWrapper.write()
behaves quite similar both acting as a wrapper aroundsys.stdout.write()
.The only difference between
print()
andOutputWrapper.write()
is:print()
accepts message string as*args
withseparator
parameter to join the the multiple strings, whereasOutputWrapper.write()
accepts single message stringBut this difference could be easily handled by explicitly joining the strings with separator and passing it to
OutputWrapper.write()
.Conclusion: You do not have to worry about the additional features provided by
print()
as there are none, and should go ahead with usingself.stdout.write()
as suggested in this answer's quoted content from Custom Management Commands document.If you are interested, you may check the source code of
BaseCommand
andOutputWrapper
classes available at: Source code fordjango.core.management.base
. It might help in clearing some of your doubts. You may also check PEP-3105 related to Python 3'sprint()
.First of all,
self.stdout
is an instance ofdjango.core.management.base.OutputWrapper
command. Itswrite
expects anstr
, notbytes
, thus you can useActually
self.stdout.write
does accept bytes but only whenever theending
is an empty string - that's because itswrite
method is definedIf
ending
is true, thenmsg.endswith(ending)
will fail ifmsg
is abytes
instance and ending is astr
.Furthermore,
print
withself.stdout
does work correctly when I set theself.stdout.ending = ''
explicitly; however doing this might mean that other code that usesself.stdout.write
expecting it to insert newlines, would fail.In your case, what I'd do is to define a
print
method for theCommand
:You can make this into your own
BaseCommand
subclass - and you can use it with different files too:When setting
self.stdout.ending
explicitly, the print command works as expected.The line ending needs to be set in
self.stdout.ending
whenfile=self.stdout
, because that is an instance ofdjango.core.management.base.OutputWrapper
.Returns