I am printing to a console in python. I am looking for a one off piece of code so that all print statments after a line of code have 4 spaces at the start. Eg.
print('Computer: Hello world')
print.setStart(' ')
print('receiving...')
print('received!')
print.setStart('')
print('World: Hi!')
Output:
Computer: Hello world
receiving...
received!
World: Hi!
This would be helpful for tabbing all of the output that is contained in a function, and setting when functions output are tabbed. Is this possible?
You can define a print function which first prints your prefix, and then internally calls the built-in print function. You can even make your custom print() function to look at the call-stack and accordingly determine how many spaces to use as a prefix:
import builtins
import traceback
def print(*objs, **kwargs):
my_prefix = len(traceback.format_stack())*" "
builtins.print(my_prefix, *objs, **kwargs)
Test it out:
def func_f():
print("Printing from func_f")
func_g()
def func_g():
print ("Printing from func_g")
func_f()
Output:
Printing from func_f
Printing from func_g
Reverting back to the built-in print() function:
When you are done with your custom printing, and want to start using the built-in print() function, just use del to "delete" your own definition of print:
del print
Why not define your own custom function and use that when needed:
def tprint(*args):
print(' ', *args)
It would be used like so:
print('Computer: Hello world')
tprint('receiving...')
tprint('received!')
print('World: Hi!')
Output:
Computer: Hello world
receiving...
received!
World: Hi!
You might want to use specific prefixes only at specific places
import sys
from contextlib import contextmanager
#contextmanager
def add_prefix(prefix):
global is_new_line
orig_write = sys.stdout.write
is_new_line = True
def new_write(*args, **kwargs):
global is_new_line
if args[0] == "\n":
is_new_line = True
elif is_new_line:
orig_write("[" + str(prefix) + "]: ")
is_new_line = False
orig_write(*args, **kwargs)
sys.stdout.write = new_write
yield
sys.stdout.write = orig_write
with add_prefix("Computer 1"):
print("Do something", "cool")
print("Do more stuffs")
with add_prefix("Computer 2"):
print("Do further stuffs")
print("Done")
#[Computer 1]: Do something cool
#[Computer 1]: Do more stuffs
#[Computer 2]: Do further stuffs
#Done
The advantage is that it's a utility function, i.e. you just have to import to use it, without having to redefine every time you write a new script.
Related
I´m trying to get last python output and I dont know how to do it.
Basically what Iím trying to do is detect the last output so, for example:
print("Hello World")
last_output = get_last_output()
print() # For avoiding confutions
print(last_output)
# Would print "\n"
print("Hello World", end="")
last_output = get_last_output()
print() # For avoiding confutions
print(last_output)
# Would print "Hello World"
I would also love this awnser would work independently of the console
Assuming "the last output" is the last not empty string written to sys.stdout, one option is to assign an object with the write(data) and flush() methods to sys.stdout, so you can save what should be the output:
import sys
class StdoutHandler:
def __init__(self):
self.last_output = ""
def start(self):
self._handled_stdout = sys.stdout
sys.stdout = self
def write(self, data: str):
# write(data="") is called for the end kwarg in print(..., end="")
if data:
self.last_output = data
self._handled_stdout.write(data)
def end(self):
sys.stdout = self._handled_stdout
def flush(self):
self._handled_stdout.flush()
stdout_handler = StdoutHandler()
stdout_handler.start()
print("Hello World")
last_output = stdout_handler.last_output
print(repr(last_output))
# Prints '\n'
print("Hello World", end="")
last_output = stdout_handler.last_output
print()
print(repr(last_output))
# Prints 'Hello World'
print("Hello", "World", end="")
last_output = stdout_handler.last_output
print()
print(repr(last_output))
# Prints 'World'
I got the idea from How to duplicate sys.stdout to a log file?
Disclaimer: #Baelfire18 asked me to help him answer this question
Suppose I have a function that prints five lines of text. I want to add prefix like 'asdf ' and suffix ' qwerty' for every line it prints on console. How to do this with decorator in python. Output generated can come from logging module or print statements in function that we want to decorate.
def my_decorator(func):
def wrapping_func(strlist):
for index, i in enumerate(strlist):
strlist[index] = 'wubalubadubdub' + i
return func(strlist)
return wrapping_func
#my_decorator
def fun(str_list):
for i in str_list:
print(i)
if __name__ == "__main__":
fun(['a', 'b'])
Duplicate question but anyways the above code is what you are looking for, the wrapping_func merely modifies the arguments that are given to the function i.e. adds a prefix and returns while calling the original function with the modified arguments with the my_decorator function just returning the wrapping_func.
Here is one sample code to demonstrate this problem.
Print statements output is customized, but not statements from logging module.
from contextlib import contextmanager
#contextmanager
def no_stdout():
import sys
old_stdout = sys.stdout
class CustomPrint():
def __init__(self, stdout):
self.old_stdout = stdout
def write(self, text):
if len(text.rstrip()):
self.old_stdout.write('custom Print--->'+ text)
sys.stdout = CustomPrint(old_stdout)
try:
yield
finally:
sys.stdout = old_stdout
def fun():
import logging
logger = logging.getLogger("tester")
logger.info("Test line from function")
print "BEFORE"
with no_stdout():
print "WHY HELLO!\n"
print "DING DONG!\n"
import logging
logger = logging.getLogger("test")
logger.info(" Hello world")
fun()
print "AFTER"
output:
BEFORE
custom Print--->WHY HELLO!
custom Print--->DING DONG!
2018-06-11 15:52:30,088 (42092) test INFO - Hello world
2018-06-11 15:52:30,092 (42092) tester INFO - Test line from function
AFTER
we see that logging modules output is not customized.
I would like to write cmd-line application with Python, which in the upper part of the terminal shows the status of something, I'd like to monitor, while in the lower part I (and my colleages) have the normal ipython interpreter, which allows us to manipulate the behaviour of the application.
In order to show the status display, I was thinking of using blessings. At first I thought about using cmd or cmd2 in order to allow run-time manipulation of the status display, but then I though, why should one implement a lot of do_something methods, when one can have the same functionality (including tab-completion and online help) for free, using the ipython interpreter.
Here is my first approach
## -- first_try.py
import time
import random
from threading import Thread
from blessings import Terminal
term = Terminal()
def display_func1():
print time.asctime()
print "Some int: ", random.randint(0, 10)
print "Some float: ", random.random()*10
def display_func2():
print time.asctime()
print "Some int: ", random.randint(0, 10)
print " details:", [random.randint(0, 10) for i in range(7)]
print "Some float: ", random.random()*10
print " details:", [random.random()*10 for i in range(5)]
class StatusDisplay(Thread):
def __init__(self, display_func):
self._text = ""
self._stop = False
self.display = display_func
Thread.__init__(self)
def run(self):
while not self._stop:
with term.location():
self.clear_top_lines()
print term.move(0, 0)
print 70*'-'
self.display()
print 70*'-'
self.print_help()
time.sleep(0.1)
def stop(self):
self._stop = True
def print_help(self):
print
print "In order to manipulate the status display"
print "type: "
print " sd.display = display_func2 and if you want to go back."
print " sd.display = display_func1"
print " Or implement your own display function and hook it into the display"
def clear_top_lines(self, n=10):
with term.location():
for i in range(n):
print term.move(0, i) + term.clear_eol()
time.sleep(2)
sd = StatusDisplay(display_func1)
sd.daemon = True
sd.start()
When I invoke this script, e.g. like this:
ipython -i --no-banner first_try.py
And hit a couple of times enter, then I have in the top of the page, something that looks like the status display, I'd like to have, and in the lower part, I can still work with the ipython interpreter, due to the -i parameter.
I think I am working here in the wrong direction, but I really would like to have this kind of feature in my application. Can somebody give me a push into the right direction?
I want to know, how can I test for a function randomly pulled from a list in a conditional statement? Here is some example code. Just ignore what the code is supposed to be printing.
import random, time
def biomeLand():
print "Biome: Land"
def biomeOcean():
print "Biome: Ocean"
def biomeDesert():
print "Biome: Desert"
def biomeForest():
print "Biome: Forest"
def biomeRiver():
print "Biome: River"
biomes = [biomeLand, biomeOcean, biomeDesert, biomeForest,
biomeRiver]
def run():
while True:
selected_biome = random.choice(biomes)()
time.sleep(0.5)
run()
Once again how can I make it so the program tests in a conditional statement when a certain function is called from the list?
maybe:
def run():
while True:
selected_biome = random.choice(biomes)
selected_biome()
if selected_biome == biomeLand:
print "biomeLand Selected"
time.sleep(0.5)
run()
You can just match them like any other variable:
def foo():
print "foo"
def bar():
print "bar"
first = foo
print (first == bar) # prints "False"
print (first == foo) # prints "True"
So in your example you can just have something like:
if selected_biome == biomeLand:
# do something
Im trying to understand how to create a custom print function.
(using python 2.7)
import sys
class CustomPrint():
def __init__(self):
self.old_stdout=sys.stdout #save stdout
def write(self, text):
sys.stdout = self.old_stdout #restore normal stdout and print
print 'custom Print--->' + text
sys.stdout= self # make stdout use CustomPrint on next 'print'
# this is the line that trigers the problem
# how to avoid this??
myPrint = CustomPrint()
sys.stdout = myPrint
print 'why you make 2 lines??...'
The code above prints this to console:
>>>
custom Print--->why you make 2 lines??...
custom Print--->
>>>
and i want to print only one line:
>>>
1custom Print--->why you make 2 lines??...
>>>
But cant figure out how to make this custom print work , i understand that there's some kind of recursion that triggers the second output to the console (i use self.write , to assign stdout to self.write himself !)
how can i make this work ? or is my approach just completely wrong...
It's not recursion. What happens is your write function is called twice, once with the text you expect, second time with just '\n'. Try this:
import sys
class CustomPrint():
def __init__(self):
self.old_stdout=sys.stdout
def write(self, text):
text = text.rstrip()
if len(text) == 0: return
self.old_stdout.write('custom Print--->' + text + '\n')
def flush(self):
self.old_stdout.flush()
What I do in the above code is I add the new line character to the text passed in the first call, and make sure the second call made by the print statement, the one meant to print new line, doesn't print anything.
Now try to comment out the first two lines and see what happens:
def write(self, text):
#text = text.rstrip()
#if len(text) == 0: return
self.old_stdout.write('custom Print--->' + text + '\n')
One solution may be to use a context manager if it's localised.
#!/usr/bin/env python
from __future__ import print_function
from contextlib import contextmanager
#############################
#contextmanager
def no_stdout():
import sys
old_stdout = sys.stdout
class CustomPrint():
def __init__(self, stdout):
self.old_stdout = stdout
def write(self, text):
if len(text.rstrip()):
self.old_stdout.write('custom Print--->' + text)
sys.stdout = CustomPrint(old_stdout)
try:
yield
finally:
sys.stdout = old_stdout
#############################
print("BEFORE")
with no_stdout():
print("WHY HELLO!\n")
print("DING DONG!\n")
print("AFTER")
The above produces:
BEFORE
custom Print--->WHY HELLO!
custom Print--->DING DONG!
AFTER
The code would need tidying up esp. around what the class should do WRT setting stdout back to what it was.
How about doing from __future__ import print_function. This way you will use Python3 print function instead of print statement from Python2. Then you can redefine the print function:
def print(*args, **kwargs):
__builtins__.print("Custom--->", *args, **kwargs)
There is a catch however, you will have to start using print function.