Pythons 'print' output doesn't call .write () method?

I thought the print statement just called the .write () method in the sys.stdout object (by default).

but by writing a subclass as follows:

 import time class logfile(file): def __init__(self, *args, **kwargs): file.__init__(self, *args, **kwargs) def write(self, logstr): if logstr[-1] != '\n': logstr += '\n' super(logfile, self).write(time.strftime('%D-%T ') + str(logstr)) 

It seems to work if I create a logfile object and call the write method, but when I try to change the sys.stdout object to a sys.stdout instance logfile it looks like print isn 't calling write . Maybe writelines ?

Using this:

 #!/usr/bin/python from myfile import logfile import sys sys.stdout = logfile('somefile', 'w') print 'this is a test' sys.stdout.write('this is another test') 

My output file "somefile" contains:

 this is a test 08/10/11-16:59:47 this is another test 

You can see that the first line in the output file is what I tried to use print , and the second line is what was used in sys.stdout.write

I thought that print simply called the write method - obviously, I was missing something basic.

+6
source share
3 answers

This is apparently a limitation of the Python 2 implementation, where print is an expression, not an expression with side effects (as in Python 3).

I rewrote the code to something that works in Python 3:

 from io import FileIO import time class logfile(FileIO): def __init__(self, *args, **kwargs): FileIO.__init__(self, *args, **kwargs) def write(self, logstr): if logstr[-1] == '\n': logstr = logstr[:-1] super(logfile, self).write(bytes(time.strftime('%D-%T ') + str(logstr), 'UTF-8')) import sys sys.stdout = logfile('somefile', 'w') print("This is a test") sys.stdout.write('this is another test') 

As far as I know, there is no way to create the same behavior in Python 2.

I also tried using from __future__ import print_function , but that didn't matter.

+4
source

If you put the file in an instance variable, it seems to work.

 import time class logfile(object): def __init__(self, *args, **kwargs): self.f = file(*args, **kwargs) def write(self, logstr): if logstr[-1] != '\n': logstr += '\n' self.f.write(time.strftime('%D-%T ') + str(logstr)) 

Unfortunately, it registers additional blank lines, here is one solution ( print '2', '3', '4' writes 3 entries):

 class logfile(object): def __init__(self, *args, **kwargs): self.f = file(*args, **kwargs) self.c = False def write(self, logstr): self.c = not self.c if logstr[-1] != '\n': logstr += '\n' if self.c: self.f.write(time.strftime('%D-%T ') + str(logstr)) 

This log writes full lines (note: print "4\n", "5" is still 2 logarithms):

 class logfile(object): def __init__(self, *args, **kwargs): self.f = file(*args, **kwargs) self.newline = True def write(self, logstr): if self.newline: self.f.write(time.strftime('%D-%T ')) self.f.write(logstr) self.newline = logstr[-1] == '\n' 

Does anyone know how to handle complete print instructions in 1 loglines?

+2
source

This article explains your problem. Basically, if sys.stdout is a subclass of file , then print bypasses sys.stdout.write and writes directly to sys.stdout.fd .

The solution to your problem is to use composition instead of the file subclass.

+1
source

Source: https://habr.com/ru/post/894766/


All Articles