How to overload print function to expand its functionality?
You can create a class with a write
method and inside of that method you can print
both stdout
as well as write
to the file.
import sys
class A(object):
def __init__(self, f):
self.f = open(f, 'w')
def __enter__(self):
return self # return instance of A which is assign to `f`.
def write(self, text):
sys.stdout.write(text) # print to the shell
self.f.write(text) # write in the file
def __exit__(self, *args):
self.f.close()
return True
with A('foo.txt') as f:
print("test0","test1","test4",sep='\n', file=f) #`file = f` calls `write` method
How to overload python's print function globally?
I don't think your question makes any sense.
First, if you're running Python 2.6, everything you import, etc., will be using print
statements, even if your own module is using the print
function. So, overloading the function will not affect anything else.
Second, you say "I need to do it because this code may be used on a system where a built-in function has to be used to generate output, otherwise no output is displayed." Well, your NewPrint
is not a built-in function, so this won't help anyway.
It's also worth noting that your NewPrint
doesn't implement most of the functionality of the print
function, and even the bit that it does implement, it does wrong (print(s)
will print s
followed by a newline). So, if you did replace the builtin print
function with yours, you'd just end up breaking most of your own code and any stdlib/third-party code you depend on.
It may be that you can accomplish what you want by creating a file-like object that replaces sys.stdout
. Otherwise, I can't see how anything could work. For example:
class FakeStdOut(object):
# … lots of other stuff to implement or inherit
def write(s):
with open("somefile.txt", "a") as f:
f.write(s)
def OverloadPrint():
sys.stdout = FakeStdOut()
But even if this works, it probably isn't what you really want. For a quick&dirty script, on a platform with a defective shell, this is sometimes a handy idea. But otherwise, it will probably cause you more trouble in the long run than coming up with a better solution. Here's just a few things that can go wrong (just as examples, not an exhaustive list)
- If you ever want to change the file the output goes to, you have to modify the script. If you instead used
>>
in the shell, you could just call the script differently. - Someone reading or debugging your code (like, say, you, three months after you forgot how it worked) will be surprised by what's going on.
- Some stdlib/third-party/coworker/etc. code you call will check that
stdout
is a tty before you make the change, and configure itself for interactive output. - Some code will print before you got a chance to redirect, and you'll spend hours trying to figure out how to reorder things to work around the problem.
- You have to know how to implement a 'file-like object' completely—and that concept is not fully defined in 2.6—or it will break with some code.
- Somewhere, there's some code that you thought was
print
ing, but it was actually, say,log
ging or writing tosys.stderr
or doing something else, so you've given yourself a false sense of security that you're now logging everything insomefile.txt
, and won't discover otherwise until 6 months later, when you desperately need that missing information to debug a problem at a customer site.
Since you've edited the question, here's some further responses:
From all the comments I guess that just using some print_() function instead of print()
Yes, that's a more reasonable option. But I probably wouldn't call it print_
. And it's simpler to put the "do or do not" logic inside the function, instead of swapping implementations in and out of the global name (especially since you're going to screw that up at some point if your code isn't all in one big module).
I worked on a project with a similar use case: We had messages we wanted to go to the syslogs, and also go to a GUI "log window" if it was open. So we wrote a glog
function that wrapped that up, and nobody complained that they wanted to write print
instead. (In fact, at least one guy on the team was very happy that he could use print
for quick-and-dirty printouts while debugging without affecting the real output, especially when he had to debug the GUI logging code.)
But that was just because we didn't have any experience with the new (back then) logging
module. Nowadays, I think I'd create a logging
Handler
implementation that writes to the GUI window, and just add that handler, and use the standard logging
methods everywhere. And it sounds like that might be the best option for you.
Also, one last probably-irrelevant side issue:
We only use the standard library and our own swig wrappers, also our developers use print as a function (getting used to 3.X).
So why not use 3.x in the first place? Obviously 3.x has the actual 3.x standard library, instead of something kind of close to the 3.x standard library if you do some __future__
statements, and SWIG works with 3.x…
How to print instances of a class using print()?
>>> class Test:
... def __repr__(self):
... return "Test()"
... def __str__(self):
... return "member of Test"
...
>>> t = Test()
>>> t
Test()
>>> print(t)
member of Test
The __str__
method is what gets called happens when you print it, and the __repr__
method is what happens when you use the repr()
function (or when you look at it with the interactive prompt).
If no __str__
method is given, Python will print the result of __repr__
instead. If you define __str__
but not __repr__
, Python will use what you see above as the __repr__
, but still use __str__
for printing.
Python change Exception printable output, eg overload __builtins__
I'll just explain the behaviour you described:
exc.__repr__()
This will just call your lambda function and return the expected string. Btw you should return the string, not print it in your lambda functions.
print(repr(exc))
Now, this is going a different route in CPython
and you can see this in a GDB session, it's something like this:
Python/bltinmodule.c:builtin_repr
will call Objects/object.c:PyObject_Repr
- this function gets the PyObject *v
as the only parameter that it will use to get and call a function that implements the built-in function repr()
, BaseException_repr
in this case. This function will format the error message based on a value from args
structure field:
(gdb) p ((PyBaseExceptionObject *) self)->args
$188 = ("name 'x' is not defined",)
The args
value is set in Python/ceval.c:format_exc_check_arg
based on a NAME_ERROR_MSG
macro set in the same file.
Update: Sun 8 Nov 20:19:26 UTC 2020
test.py:
import sys
import dis
def main():
try:
x
except NameError as exc:
tb = sys.exc_info()[2]
frame, i = tb.tb_frame, tb.tb_lasti
code = frame.f_code
arg = code.co_code[i + 1]
name = code.co_names[arg]
print(name)
if __name__ == '__main__':
main()
Test:
# python test.py
x
Note:
I would also recommend to watch this video from PyCon 2016.
Related Topics
How to Set a Default Parameter Equal to Another Parameter Value
Change the Colors Within Certain Range to Another Color Using Opencv
Naming Conflict with Built-In Function
Bin Elements Per Row - Vectorized 2D Bincount for Numpy
Changing Iteration Variable Inside for Loop in Python
I Expect 'True' But Get 'None'
Python 3.5 - "Geckodriver Executable Needs to Be in Path"
How to Make My Player Rotate Towards Mouse Position
Wrapping a C Library in Python: C, Cython or Ctypes
What's the Best Practice Using a Settings File in Python
Pyplot Common Axes Labels for Subplots
How to Upgrade to Python 3.6 with Conda
How to Change the Python Version in Visual Studio Code
How to Find a Particular JSON Value by Key
Differencebetween Len() and Sys.Getsizeof() Methods in Python