I have written code that works for my cause and displays the results in the terminal:
print 'The following results are found:'
# some code iterations here
...
...
print 'User - {0}, Title - {1}'.format(...)
Currently, I am trying to implement a new optional argument such that it allows me to choose whether I would like the above results to be written to a text file.
While I can get it to work, it is not in the most elegant method:
# output_to_path is a boolean argument here.
if output_to_file:
# file_path, I use `open(file_dir, "w")`
print >> file_path, 'The following results are found:'
print 'The following results are found:'
# some code iterations here
...
...
if output_to_file:
print 'User - {0}, Title - {1}'.format(...)
print 'User - {0}, Title - {1}'.format(...)
Is it possible to only write the above print statements once, whether output_to_file is true or false? I ask as I do have a ton of print statements to begin with.
Here's a way to do it with a context manager, which is similar to what's being done in the answer to the question I referred you to in a comment below your question.
The twist is that in order to be able to selectively turn output to the files on and off as desired, the simplest route seemed to be implement it as a class (instead of applying the contextlib's #contextmanager decorator to a function as was done there).
Hope this isn't too much code...
import sys
class OutputManager(object):
""" Context manager that controls whether sysout goes only to the interpreter's
current stdout stream or to both it and a given file.
"""
def __init__(self, filename, mode='wt'):
self.output_to_file = True
self.saved_stdout = sys.stdout
self.file = open(filename, mode)
sys.stdout = self
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
sys.stdout = self.saved_stdout # Restore.
self.file.close()
def write(self, message):
self.saved_stdout.write(message)
if self.output_to_file:
self.file.write(message)
def enable(self):
self.output_to_file = True
def disable(self):
self.output_to_file = False
if __name__ == '__main__':
# Sample usage.
with OutputManager('cmtest.txt') as output_manager:
print 'This line goes to both destinations.'
output_manager.disable()
print 'This line goes only to the display/console/terminal.'
output_manager.enable()
print 'Once again, to both destinations.'
You could write a function that does what you want:
def custom_print(message):
print(message) # always prints to stdout
if output_to_file:
print >> file_path, message
Then you call it like this:
custom_print('The following results are found:')
...
custom_print('User - {0}, Title - {1}'.format(...))
Related
Let's say I have a class like so:
class Shell:
def cat(self, file):
try:
with open(file, 'r') as f:
print f.read()
except IOError:
raise IOError('invalid file location: {}'.format(f))
def echo(self, message):
print message
def ls(self, path):
print os.listdir(path)
In a javascript context, you might be able to do something like "Class"[method_name](), depending on how things were structured. I am looking for something similar in python to make this a "simulated operating system". EG:
import os
def runShell(user_name):
user_input = None
shell = Shell()
while(user_input != 'exit' or user_input != 'quit'):
user_input = raw_input('$'+ user_name + ': ')
...
now, the idea is they can type in something like this...
$crow: cat ../my_text
... and behind the scenes, we get this:
shell.cat('../my_text')
Similarly, I would like to be able to print all method definitions that exist within that class when they type help. EG:
$crow: help\n
> cat (file)
> echo (message)
> ls (path)
is such a thing achievable in python?
You can use the built-in function vars to expose all the members of an object. That's maybe the simplest way to list those for your users. If you're only planning to print to stdout, you could also just call help(shell), which will print your class members along with docstrings and so on. help is really only intended for the interactive interpreter, though, so you'd likely be better off writing your own help-outputter using vars and the __doc__ attribute that's magically added to objects with docstrings. For example:
class Shell(object):
def m(self):
'''Docstring of C#m.'''
return 1
def t(self, a):
'''Docstring of C#t'''
return 2
for name, obj in dict(vars(Shell)).items():
if not name.startswith('__'): #filter builtins
print(name, '::', obj.__doc__)
To pick out and execute a particular method of your object, you can use getattr, which grabs an attribute (if it exists) from an object, by name. For example, to select and run a simple function with no arguments:
fname = raw_input()
if hasattr(shell, fname):
func = getattr(shell, fname)
result = func()
else:
print('That function is not defined.')
Of course you could first tokenize the user input to pass arguments to your function as needed, like for your cat example:
user_input = raw_input().split() # tokenize
fname, *args = user_input #This use of *args syntax is not available prior to Py3
if hasattr(shell, fname):
func = getattr(shell, fname)
result = func(*args) #The *args syntax here is available back to at least 2.6
else:
print('That function is not defined.')
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'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
I feel like I should know this, but I haven't been able to figure it out...
I want to get the name of a method--which happens to be an integration test--from inside it so it can print out some diagnostic text. I can, of course, just hard-code the method's name in the string, but I'd like to make the test a little more DRY if possible.
This seems to be the simplest way using module inspect:
import inspect
def somefunc(a,b,c):
print "My name is: %s" % inspect.stack()[0][3]
You could generalise this with:
def funcname():
return inspect.stack()[1][3]
def somefunc(a,b,c):
print "My name is: %s" % funcname()
Credit to Stefaan Lippens which was found via google.
The answers involving introspection via inspect and the like are reasonable. But there may be another option, depending on your situation:
If your integration test is written with the unittest module, then you could use self.id() within your TestCase.
This decorator makes the name of the method available inside the function by passing it as a keyword argument.
from functools import wraps
def pass_func_name(func):
"Name of decorated function will be passed as keyword arg _func_name"
#wraps(func)
def _pass_name(*args, **kwds):
kwds['_func_name'] = func.func_name
return func(*args, **kwds)
return _pass_name
You would use it this way:
#pass_func_name
def sum(a, b, _func_name):
print "running function %s" % _func_name
return a + b
print sum(2, 4)
But maybe you'd want to write what you want directly inside the decorator itself. Then the code is an example of a way to get the function name in a decorator. If you give more details about what you want to do in the function, that requires the name, maybe I can suggest something else.
# file "foo.py"
import sys
import os
def LINE( back = 0 ):
return sys._getframe( back + 1 ).f_lineno
def FILE( back = 0 ):
return sys._getframe( back + 1 ).f_code.co_filename
def FUNC( back = 0):
return sys._getframe( back + 1 ).f_code.co_name
def WHERE( back = 0 ):
frame = sys._getframe( back + 1 )
return "%s/%s %s()" % ( os.path.basename( frame.f_code.co_filename ),
frame.f_lineno, frame.f_code.co_name )
def testit():
print "Here in %s, file %s, line %s" % ( FUNC(), FILE(), LINE() )
print "WHERE says '%s'" % WHERE()
testit()
Output:
$ python foo.py
Here in testit, file foo.py, line 17
WHERE says 'foo.py/18 testit()'
Use "back = 1" to find info regarding two levels back down the stack, etc.
I think the traceback module might have what you're looking for. In particular, the extract_stack function looks like it will do the job.
To elaborate on #mhawke's answer:
Rather than
def funcname():
return inspect.stack()[1][3]
You can use
def funcname():
frame = inspect.currentframe().f_back
return inspect.getframeinfo(frame).function
Which, on my machine, is about 5x faster than the original version according to timeit.