I'm wishing to print a character to the start of every line in python code. In particular, I want to print a "|" to the start of every outputted line. What would be the best way to achieve this in python?
Using Python 3? Replace print:
_realprint = print
def print(*args, **kwargs):
_realprint('|', end='')
_realprint(*args, **kwargs)
print.__doc__ = _realprint.__doc__
Now everything output by print will be prefixed by '|'. Extra credit for replacing \n with \n| in your _realprint() calls, remembering when called with end equal to something other than \n, etc. This should get you through 99% of cases, though.
Make your own file-like that defines write() and replace sys.stdout.
import sys
class forewrap(object):
def __init__(self, origfile, cseq='|'):
self.file = origfile
self.cseq = cseq
self.seen = False
def write(self, txt):
if not (self.seen and txt == '\n'):
self.seen = True
self.file.write(self.cseq)
else:
self.seen = False
self.file.write(txt)
print 'foo'
sys.stdout = forewrap(sys.stdout)
print 'foo'
print
print 'bar'
Related
I am currently writing myself a program in python 3.7 and was wanting to add a timestamp to the front of my printing in the format:
<hh:mm:ss> WhateverImPrinting
I took a look at other forums and I get some code which used sys.stdout, overwriting the text using the write function.
My issue is it is returning the timestamp both before and after my print.
e.g. <14:21:51> Hello<14:21:51>
This should be:
<14:21:51> Hello
My code:
old_f = sys.stdout # Get old print output
class PrintTimestamp:
# #staticmethod
def write(self, x):
old_f.write("<{}> {}".format(str(pC.Timestamp.hhmmss()), x))
# #staticmethod
def flush(self):
pass
sys.stdout = PrintTimestamp() # Set new print output
I have run this after all my classes and functions, but before if __name__ == '__main__'
You can simply override print function in Python 3.x:
from datetime import datetime
old_print = print
def timestamped_print(*args, **kwargs):
old_print(datetime.now(), *args, **kwargs)
print = timestamped_print
then
print("Test")
should print
2019-09-30 01:23:44.67890 Test
Here you go.
from datetime import datetime
class PrintTimeStamp():
def write(self,x):
ts = str(datetime.now.hour())+":"+str(datetime.now().minute)+":"+str(datetime.now().second)
print("<{}> {}".format(str(ts),x)
pts = PrintTimeStamp()
pts.write("test")
Is there a way to save data after it was printed to the screen?
for example:
lets have some arbitrary function
def main():
if something:
for i in range(n):
output= "%f %f" %(n,d)
print output
if something:
for i in range(n):
output="%f %f" %(n,d)
print output
fileout=open("data.csv", "a")
fileout.write(output)
this will only write the last data for the last range in for loop.
Edit: I want to ask a user if she/he wants to save that data
Declare your output variable(s) at the highest level of scope in your program first. This will allow it to be written to a file in the manner you've programmed.
If you want to prompt a user for a location to save the file(s), that's merely this:
out1 = raw_input("Where would you like to save this? ")
You can do the same for another output file variable.
just use this in the if conditions:
print >>fileout, output #this will save the output to the data.csv file
Change your code...
1: If you really want to use print, change sys.stdout to a different stream
2: use files
1
import sys
oldstdout=sys.stdout
f=open("myfile","w")
sys.stdout=f
def main():
if something:
for i in range(n):
print "%f %f"%(n,d)
if something:
for i in range(n):
print "%f %f"%(n,d)
2
f=open("myfile","w")
def main():
if something:
for i in range(n):
f.write("%f %f"%(n,d))
if something:
for i in range(n):
f.write("%f %f"%(n,d))
Here is a (somewhat pathological) example that will let you both print and save the statements that you print in a global list (which we'll call OUTPUT):
import sys
OUTPUT = []
def print_wrapper(method):
class result(object):
def __init__(self, file_obj):
self.file_obj = file_obj
def __getattr__(self, name):
return getattr(self.file_obj, name)
def write(self, value):
OUTPUT.append(value)
return self.file_obj.write(value)
return result(method)
original_stdout = sys.stdout
sys.stdout = print_wrapper(original_stdout)
# This will still print, but will add 'Hi' and '\n' to OUTPUT as well
print 'Hi'
# This will still print, but will add 'None' and '\n' to OUTPUT as well
print None
# This uses the original stdout to print, so won't change OUTPUT
original_stdout.write(repr(OUTPUT))
original_stdout.write('\n')
or you could alternately prepare yourself for Python 3 (or just use it) and wrap the print method itself:
from __future__ import print_function # must have Python >= 2.6
OUTPUT = []
def wrap_print(method):
def result(value):
OUTPUT.append(value)
return method(value)
return result
old_print = print
print = wrap_print(old_print)
print('Hi')
print(None)
old_print(OUTPUT)
I thought the print statement just called the .write() method on the sys.stdout (by default) object.
but having written a subclass like this:
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 trying to change the sys.stdout object to an instance of the logfile it appears as though 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 the first line in the output file is what I tried to print and the second line is what was used in sys.stdout.write
I thought print just called the write method- clearly I'm missing something basic.
Apparently this is an limitation of the implementation of Python 2 where print is a statement rather than an expression with side-effects (as it is 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 behaviour in Python 2.
I also tried using from __future__ import print_function but that made no difference.
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 logs extra empty 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 one logs full lines (note: print "4\n", "5" is still 2 loglines):
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 anybody know how to handle full print statements in 1 loglines?
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 subclassing file.
I'm trying to learn programming through Python and I like to know if it's possible to get just the return value of a function and not its other parts. Here's the code:
Let's say, this is the main function:
variable_a = 5
while variable_a > 0 :
input_user = raw_input(": ")
if input_user == "A":
deduct(variable_a)
variable_a = deduct(variable_a)
else:
exit(0)
Then this is the deduct function:
def deduct(x):
print "Hello world!"
x = x - 1
return x
What happens is that, it does the calculation and deduct until variable_a reaches 0. However, "Hello world!" gets printed twice, I think because of variable_a = deduct(variable_a) (correct me if I'm wrong). So I was thinking, can I just capture the return value of deduct() and not capture the rest? So that in this instance, after going through deduct(), variable_a would just have a plain value of 2 (without the "Hello world!").
Am I missing things? :?
Editor's note: I remove the blank lines, so it can be pasted to REPL.
The printing of "Hello world" is what's known as a side effect - something produced by the function which is not reflected in the return value. What you're asking for is how to call the function twice, once to produce the side effect and once to capture the function return value.
In fact you don't have to call it twice at all - once is enough to produce both results. Simply capture the return value on the one and only call:
if input_user == "A":
variable_a = deduct(variable_a)
else:
If you don't want your function to print output, the correct solution is to not use print in it. :P
The first time you call deduct, it doesn't do anything except print that message, so you could probably just remove that line and be fine.
However, there is a slightly messy way to suppress print statements. You can temporarily replace your program's output file with a placeholder that does nothing.
import sys
class FakeOutput(object):
def write(self, data):
pass
old_out = sys.stdout
sys.stdout = FakeFile()
print "Hello World!" # does nothing
sys.stdout = old_out
print "Hello Again!" # works normally
You could even make a context manager to make this more convenient.
import sys
class FakeOutput(object):
def __enter__(self):
self.out_stdout = sys.stdout
sys.stdout = self
return self
def __exit__(self, *a):
sys.stdout = self.out_stdout
def write(self, data):
pass
print "Hello World!" # works
with FakeOutput():
print "Hello Again!" # doesn't do anything
print "Hello Finally!" # works
I have a context manager that captures output to a string for a block of code indented under a with statement. This context manager yields a custom result object which will, when the block has finished executing, contain the captured output.
from contextlib import contextmanager
#contextmanager
def capturing():
"Captures output within a 'with' block."
from cStringIO import StringIO
class result(object):
def __init__(self):
self._result = None
def __str__(self):
return self._result
try:
stringio = StringIO()
out, err, sys.stdout, sys.stderr = sys.stdout, sys.stderr, stringio, stringio
output = result()
yield output
finally:
output._result, sys.stdout, sys.stderr = stringio.getvalue(), out, err
stringio.close()
with capturing() as text:
print "foo bar baz",
print str(text) # prints "foo bar baz"
I can't just return a string, of course, because strings are immutable and thus the one the user gets back from the with statement can't be changed after their block of code runs. However, it is something of a drag to have to explicitly convert the result object to a string after the fact with str (I also played with making the object callable as a bit of syntactic sugar).
So is it possible to make the result instance act like a string, in that it does in fact return a string when named? I tried implementing __get__, but that appears to only work on attributes. Or is what I want to do not really possible?
How to make a class that acts like a string?
Subclass str
import os
class LikeAStr(str):
'''Making a class like a str object; or more precisely
making a str subclass with added contextmanager functionality.'''
def __init__(self, diff_directory):
self._iwd = os.getcwd()
self._cwd = diff_directory
def __enter__(self):
return self
def __exit__(self, ext_typ, exc_value, traceback):
try: os.chdir(self._iwd) # might get deleted within the "with" statement
except: pass
def __str__(self):
return self._cwd
def __repr__(self):
return repr(self._cwd)
astr = LikeAStr('C:\\')
with LikeAStr('C:\\') as astr:
print 1, os.getcwd()
os.chdir( astr ) # expects str() or unicode() not some other class
print 2, os.getcwd()
#
# out of with block
print 3, os.getcwd()
print 4, astr == 'C:\\'
Output:
1 D:\Projects\Python\
2 C:\
3 D:\Projects\Python\
4 True
I don't believe there is a clean way to do what you want.
text is defined in the modules' globals() dict.
You would have to modify this globals() dict from within the capturing object:
The code below would break if you tried to use the with from within a function, since then text would be in the function's scope, not the globals.
import sys
import cStringIO
class capturing(object):
def __init__(self,varname):
self.varname=varname
def __enter__(self):
self.stringio=cStringIO.StringIO()
self.out, sys.stdout = sys.stdout, self.stringio
self.err, sys.stderr = sys.stderr, self.stringio
return self
def __exit__(self,ext_type,exc_value,traceback):
sys.stdout = self.out
sys.stderr = self.err
self._result = self.stringio.getvalue()
globals()[self.varname]=self._result
def __str__(self):
return self._result
with capturing('text') as text:
print("foo bar baz")
print(text) # prints "foo bar baz"
# foo bar baz
print(repr(text))
# 'foo bar baz\n'
At first glance, it looked like UserString (well, actually MutableString, but that's going away in Python 3.0) was basically what I wanted. Unfortunately, UserString doesn't work quite enough like a string; I was getting some odd formatting in print statements ending in commas that worked fine with str strings. (It appears you get an extra space printed if it's not a "real" string, or something.) I had the same issue with a toy class I created to play with wrapping a string. I didn't take the time to track down the cause, but it appears UserString is most useful as an example.
I actually ended up using a bytearray because it works enough like a string for most purposes, but is mutable. I also wrote a separate version that splitlines() the text into a list. This works great and is actually better for my immediate use case, which is removing "extra" blank lines in the concatenated output of various functions. Here's that version:
import sys
from contextlib import contextmanager
#contextmanager
def capturinglines(output=None):
"Captures lines of output to a list."
from cStringIO import StringIO
try:
output = [] if output is None else output
stringio = StringIO()
out, err = sys.stdout, sys.stderr
sys.stdout, sys.stderr = stringio, stringio
yield output
finally:
sys.stdout, sys.stderr = out, err
output.extend(stringio.getvalue().splitlines())
stringio.close()
Usage:
with capturinglines() as output:
print "foo"
print "bar"
print output
['foo', 'bar']
with capturinglines(output): # append to existing list
print "baz"
print output
['foo', 'bar', 'baz']
I think you might be able to build something like this.
import StringIO
capturing = StringIO.StringIO()
print( "foo bar baz", file= capturing )
Now 'foo bar baz\n' == capturing.getvalue()
That's the easiest. It works perfectly with no extra work, except to fix your print functions to use the file= argument.
How to make a class that acts like a string?
If you don't want to subclass str for whatever reason:
class StrBuiltin(object):
def __init__(self, astr=''):
self._str = astr
def __enter__(self):
return self
def __exit__(self, ext_typ, exc_value, traceback):
pass # do stuff
def __str__(self):
return self._str
def __repr__(self):
return repr(self._str)
def __eq__(self, lvalue):
return lvalue == self._str
def str(self):
'''pretend to "convert to a str"'''
return self._str
astr = StrBuiltin('Eggs&spam')
if isinstance( astr.str(), str):
print 'Is like a str.'
else:
print 'Is not like a str.'
I know you didn't want to do str(MyClass) but MyClass.str() kind of implies, to me, that this class is expected to expose itself as a str to functions which expect a str as part of the object. Instead of some unexpected result of "who know's what would be returned by str( SomeObject ).
This is an old question but is an interesting one.
Using the idea from #S.Lott you can use contextmanagers to create a more robust and reusable tool:
#contextmanager
def redefine_print(stream):
global print
from functools import partial, wraps
old_print = print
try:
print = wraps(print)(partial(print, file=stream))
yield print
finally:
print = old_print
sample use with file-like objects:
with open('file', 'a+') as stream:
print('a') # print in the interface
with redefine_print(stream):
print('b') # print in the file
print('c') # print in the interface
stream.seek(0)
print(stream.readlines())
sample use with StringIO objects
import io
stream = io.StringIO()
with redefine_print(stream) as xprint:
print('b') # add to the ioStream
xprint('x') # same as print, just to see how the object works
print(stream.getvalue()) # print the intercepted value
print(xprint.__doc__) # see how #wraps helps to keep print() signature