I'm working on an open source python library that uses a verbose_print command to log outputs in the console. Currently it looks like this:
def sys_write_flush(s):
""" Writes and flushes without delay a text in the console """
sys.stdout.write(s)
sys.stdout.flush()
def verbose_print(verbose, s):
""" Only prints s (with sys_write_flush) if verbose is True."""
if verbose:
sys_write_flush(s)
I proposed a change that looks like this:
def verbose_print(verbose, *args):
""" Prints everything passed except the first argument if verbose is True."""
if verbose:
print(*args)
Apart from the fact that it fails on Python 2 (bonus point for fixing this!), I thought that this would be better and more idiomatic. The advantages are, that you can treat verbose_print exactly like print, except that the first argument has to be True or False.
The repo owner replied with this message:
I should have documented this one, but basically the issue was that in
some consoles (and in the IPython notebook, at least at the time),
"print" commands get delayed, while stdout.flush are instantaneous, so
my method was better at providing feedback.
I would be against changing it to print unless it solves some known
issues.
Is this still a valid concern? Would print() followed by sys.stdout.flush() avoid the delay? Are there any better ways to write this?
Source
Quote from the docs:
print evaluates each expression in turn and writes the resulting
object to standard output.
Standard output is defined as the file object named stdout in the
built-in module sys. If no such object exists, or if it does not
have a write() method, a RuntimeError exception is raised.
According to this, print writes to sys.stdout, so, yes, doing a sys.stdout.flush() after printing will have the same effect as flushing after sys.stdout.write-ing.
The syntax print(*a) fails in Python 2 because print isn't a function, but a statement, and that fun(*stuff) construct is only applicable to functions.
In Python 3 print(*a) passes whatever a contains to the function print as separate arguments, but this is equal to passing a big string:
separator = ' '
print separator.join(map(str, iterable))
So, your code could look like this:
def verbose_print(verbose, *args):
""" Prints everything passed except the first argument if verbose is True."""
if verbose:
print " ".join(map(str, args))
sys.stdout.flush()
Although I don't see why this can be faster or more readable than the original.
Related
Long story short, I am writing python code that occasionally causes an underlying module to spit out complaints in the terminal that I want my code to respond to. My question is if there is some way that I can take in all terminal outputs as a string while the program is running so that I might parse it and execute some handler code. Its not errors that crash the program entirely and not a situation where I can simply do a try catch. Thanks for any help!
Edit: Running on Linux
there are several solutions to your need. the easiest would be to use a shared buffer of sort and get all your package output there instead of stdout (with regular print) thus keeping your personal streams under your package control.
since you probably already have some code with print or you want for it to work with minimal change, i suggest use the contextlib.redirect_stdout with a context manager.
give it a shared io.StringIO instance and wrap all your method with it.
you can even create a decorator to do it automatically.
something like:
// decorator
from contextlib import redirect_stdout
import io
import functools
SHARED_BUFFER = io.StringIO()
def std_redirecter(func):
#functools.wrap(func)
def inner(*args, **kwargs):
with redirect_stdout(SHARED_BUFFER) as buffer:
print('foo')
print('bar')
func(*args, **kwargs)
return inner
// your files
#std_redirecter
def writing_to_stdout_func():
print('baz')
// invocation
writing_to_stdout_func()
string = SHARED_BUFFER.getvalue() // 'foo\nbar\nbaz\n'
[printing slowly (Simulate typing)
I got my answer from the link above but it only works when you put the string as a parameter when calling function.
I want the code to print slowly every time when I use print().
is it possible?
Yes, you can do it like this, however, I think it's not a good idea:
import time
def dprint(string):
for letter in string:
__builtins__.print(letter,end = '', flush=True)
time.sleep(.1)
__builtins__.print("")
print = dprint
print("something")
Yes, you can do it using the stdout version as below.
import sys, time
def print(s):
for letter in s:
sys.stdout.write(letter)
time.sleep(.1)
print("Foo")
Changing the default behaviour of print() is not recommended and was only introduced for purpose of porting Python 2 programs easily. Moreover overloading the print function without a special parameter will make the default functionality of print() moot.
Create another function with adds a delay to the prints. Also remember that you cannot use print() because it appends a new line. You’ll have to you sys.stdout.write()
So a basic function would look like:
def typrint(x):
for i in len(x):
sys.stdout.write(x[i])
sleep(0.05)
sys.stdout.write(“\n”)
Check this article to see why Python updated print() to a function
I am using this as the solution for the problem,
import sys,time
def delay(str):
for i in str:
sys.stdout.write(i)
sys.stdout.flush()
time.sleep(0.04)
Note: You need to add in every print statement or here "delay" statement "\n".
I'm looking for the cleanest way to print a variable dynamically in python 3.
I want to repeatedly call psutil.virtual_memory() and print its return-value in place.
Something like this:
import psutil
import time
memory = psutil.virtual_memory()
while True:
print(f"Memory: {memory}")
time.sleep(0.5)
Ofcourse that wouldn't be dynamic. I want "memory" to update every 0.5 seconds on the same line.
I couldn't seem to find a clean example of how to do this in this manner.
UPDATE: I'm also wanting to learn how I can do this with multi-line print statements.
Like this
Memory: 500MB
CPU Usage: 25%
Just add print(..., end='\r') to the end of your printing statement.
This brings the cursor to the beginning of the line, so subsequent prints will overwrite it.
f-strings allow you to directly print a function call or expression in the first place, so do that. (No need to store the stale return value to a variable, in the first place)
while True:
print(f"Memory: {psutil.virtual_memory()}")
time.sleep(0.5)
UPDATE: after you accepted an answer, we infer that when you say "print the value in-place", you actually mean "overwrite the output (on console) from previous print"
"in-place" is actually a different term that usually refers to "variable assignment without allocating new memory". Better to say "overwrite on the console".
Add carriage return with flush for print.
import psutil
import time
def memory():
return psutil.virtual_memory()
while True:
print(f"Memory: {memory()}", end="\r", flush=True)
time.sleep(0.5)
I use a internal library that prints a lot (one script could print 40000 lines in total), and I suppose it may have bad impact in performance. This is a library developed by another team in my company and do a lot of calculations, they print to debug errors (and I know this is not a good habit but it's too late because of 100 scripts already on production)
and I'm developing a script that uses 100 scripts to produce the result.
How can I decide to turn all this print off ?
I'm not asking how to print these lines to file, but completely omit it
Replace sys.stdout with an object that eats the output:
import sys
class Null:
def write(self, text):
pass
def flush(self):
pass
print "One" # This gets output OK
old_stdout = sys.stdout
sys.stdout = Null()
print "Two" # This disappears
sys.stdout = old_stdout
print "Three" # Output, back to normal
The best way is to simply remove the print statements as there
is no overhead whatsoever.
Alternatively, you can redirect the output to /dev/null, which will
effectively remove the I/O overhead but will not remove the syscall.
To spare the syscall you can replace sys.stdout with a Writer which does nothing.
For example:
class NullWriter():
def write(self, s): pass
sys.stdout = NullWriter()
Apparently, this has been asked and solved before. Also here.
In case you're using python 3, you can overload the print function as
seen in this answer:
def print(*args, **kwargs):
pass
I want to automatically indent the next line of a console app but the user needs to be able to remove it. sys.stdout.write and print make undeletable characters and I can't write to sys.stdin (as far as I know). I'm essentially trying to get smart indenting but I can only nest deeper and deeper. Any ideas on how to climb back out?
Edit: I should have noted that this is part of a Windows program that uses IronPython. While I could do something much fancier (and might in the future), I am hoping to quickly get a reasonably pleasant experience with very little effort as a starting point.
The cmd module provides a very simple interface for creating a command line interface to your program. It might not be able to put some buffer characters in front of the next line but if you're looking for an obvious way to let your users know that the command has returned, it can provide a shell-like prompt at the beginning of each line. If you already have functions defined for your program, integrating them into a processor would be a matter of writing a handler that access the function:
import cmd
import math
def findHpyot(length, height):
return math.sqrt(length **2 + height **2)
class MathProcessor(cmd.Cmd):
prompt = "Math>"
def do_hypot(self, line):
x = raw_input("Length:")
y = raw_input("Height:")
if x and y:
try:
hypot = findHypot(float(x), float(y))
print "Hypot:: %.2f" %hypot
except ValueError:
print "Length and Height must be numbers"
def do_EOF(self, line):
return True
def do_exit(self, line):
return True
def do_quit(self, line):
return True
if __name__ == "__main__":
cmdProcessor = MathProcessor()
cmdProcessor.cmdloop()
Things to consider when writing an interactive shell using cmd
The name after do_ is the command that your users will use so that in this example, the available commands will be hypot, exit, quit, and help.
Without overriding do_help, calling help will give you a list of available commands
Any call that you want to quit the program should return True
If you want to process entries from the function call, say you wanted to be able to handle a call like "hypot 3 4" you can use the local line variable in the function call