Python - tie built in function to created function - python

I want to keep track of the last time my python program printed something to the console.
I created this function:
def updateLastPrintTime():
global lastPrintTime
lastPrintTime = time.time()
And I'm calling it after each print statement.
This works fine, however, I have a lot of print statements and I want to update lastPrintTime after each and every printing.
If print was not a built in function, this is what I would do:
def print():
updateLastPrintTime()
# rest of 'print' code ...
But I can't figure out how to do that with a built-in function, especially since they are written in C.
Any help would be appreciated.

Based on this answer: overload print python
You could do something like this:
from __future__ import print_function
import time
last_print_time = time.time() # initialise global var
try:
import __builtin__
except ImportError:
# Python 3
import builtins as __builtin__
# overload the print function
def print(*args, **kwargs):
global last_print_time
last_print_time = time.time() # update variable
return __builtin__.print(*args, **kwargs) # print the message

You can assign the builtins print to another name and then you can override print
_print = print
def print(*args, **kwargs):
_print("Hello,", *args, **kwargs)
print("world!")
Alternatively, you can also get the builtins print from the builtins module e.g.
import builtins
def print(*args, **kwargs):
builtins.print("Hello,", *args, **kwargs)
print("world!")

Related

How to override the builtin method "print()"

I need to customize the print(), so that it does something else besides printing what I want. Is there a way to override it?
Here is A Page That Will Help You With Overriding Functions!
Here is A Way To Override print! (Making a New print)
Code:
from __future__ import print_function
try:
import __builtin__
except ImportError:
import builtins as __builtin__
def print(*args, **kwargs):
"""My custom print() function."""
__builtin__.print('your text')
return __builtin__.print(*args, **kwargs)
print()
Output:
your text
The Line __builtin__.print('your text') would Print 'Your Text', you can put other function Also Instead of Print, it would Print Your Given Text also As The Return Line Says It to, it used the built in print function!
The Second Thing That you can Do is That You Can Remove The Return Line so The Function wouldn't Print Anything To The Console
Hope This Helps
one option is to use contextlib.redirect_stdout:
from contextlib import redirect_stdout
with open('file.txt', 'a') as file, redirect_stdout(file):
print('hello')
if you need both printing and saving to a file, this may work:
from contextlib import redirect_stdout
from sys import stdout
from io import StringIO
class MyOutput(StringIO):
def __init__(self, file):
super().__init__()
self.file = file
def write(self, msg):
stdout.write(msg)
self.file.write(msg)
with open('file.txt', 'a') as file, redirect_stdout(MyOutput(file=file)):
print('hello')
You can override the print() method but you have to create class and then override the "str" dunder method (print() uses "str" implementation in backend). Here is the code.
a = 2
print(a)
class abc:
def __init__(self,x):
self.x = x
def __str__(self):
return "The value is " + str(self.x)
a = abc(2)
print(a)

override print method in current class python3

Not sure how I would accomplish overriding the print('something') function do do something else in the class I am in.
For example, I have the following code:
import app
from app.helper import ws_send
class TemplateSubJob:
def __init__(self, sessiondata, sid, payload):
self.session = sessiondata
self.sid = sid
self.payload = payload
def startme(self):
ws_send(self.sid, self.payload, 'Send some output to the user...')
ws_send(self.sid, self.payload, 'Send something else to the user...')
print('test')
return b'xlsx_bytes_output'
I want to override the function print('something') to take what is passed and do something with it.
In my case I want to create a print function that does what ws_send() is doing, except only take a string.
Something like the following:
def print(string):
ws_send(self.sid, self.payload, string)
print('now i am being sent through ws_send instead of stdout')
How can I accomplish this?
UPDATE:
The reasoning for this is so anyone who is adding code to mine, does not need to modify their code or script to use my functions. I can hijack the print function that they are already using.
You can overload the print function with the following syntax:
from __future__ import print_function
try:
# python2
import __builtin__
except ImportError:
# python3
import builtins as __builtin__
def print(*args, **kwargs):
__builtin__.print('New print function')
return __builtin__.print(*args, **kwargs)
E: Fixed bad import, as pointed out in the comment
So I'm not going to go over the why you're using a print statement in that given case, but for Python 3, within your class description
class TemplateSubJob:
def __init(self, ):
# and other methods
def __str__(self, ):
return 'String description here'
which will return the given string when someone tries to print the given object. For example, when I instantiate, I can then call the print function directly following the instantiation, which will return any strings returned by the str function above
myobject = TemplateSubJob()
print(myobject)
For redirecting print to variable(string), use this:
from io import StringIO # Python2 use: from cStringIO import StringIO
import sys
old_stdout = sys.stdout
sys.stdout = mystdout = StringIO()
# blah blah lots of code ...
sys.stdout = old_stdout
# examine mystdout.getvalue()
Source: https://stackoverflow.com/a/1218951/4718434
For redirect it to file, use this:
https://stackoverflow.com/a/4675744/4718434

Jupyter magic defined from instance method

I am writing a class that sends slack messages to users when processes have finished. I thought it would be useful to provide a Jupyter magic so that users can be notified when the cell is executed.
The class already provides a decorator, so I figured I'd just wrap a cell execution in a decorated function.
from IPython.core.magic import register_cell_magic
from IPython import get_ipython
import functools
class MyClass(object):
def decorate(self, f):
#functools.wraps(f)
def wrapped(*args, **kwargs):
r = f(*args, **kwargs)
print('Send a message here!')
return r
return wrapped
#register_cell_magic
def magic(self, line, cell):
ip = get_ipython()
#self.decorate
def f():
return ip.run_cell(cell)
return f()
So then I'd do:
obj = MyClass()
# ----- NEW CELL
%%obj.magic
'''do some stuff'''
But I get
>> UsageError: Cell magic `%%obj.magic` not found.
I found out that the magic is registered under its name (above, magic), so %%magic works. But then the arguments are all messed up because there is no self in the mix.
I want the magic to be an instance method so that config (set in __init__ can be used). Is there any way to do this?
Here are a couple hacky solutions I don't want to implement unless I really have to:
Register a regular function with the instance as an argument. I don't want to add that line of code to the notebook, I want to use an instance method.
Register a regular function that constructs an instance on the fly.
This is the best I can come up with, and it's #1 on the list of the things I didn't want to do.
from IPython.core.magic import register_cell_magic
from IPython import get_ipython
import functools
class MyClass(object):
def decorate(self, f):
#functools.wraps(f)
def wrapped(*args, **kwargs):
r = f(*args, **kwargs)
print('Send a message here!')
return r
return wrapped
def register_magic(self):
#register_cell_magic
def magic(line, cell):
ip = get_ipython()
#self.decorate
def f():
return ip.run_cell(cell)
return f()
Then
obj = MyClass()
obj.register_magic()
# ------
%%magic
...

Custom print function yield from sub function

I customized the print function to print to console and also send print lines to an object so I can pipe them to a gui using a yield function. This works fine, until my function calls a sub function and that sub function prints to console. If I import my custom print into that subfunction, it doesn't work because that print is yielding results to the subfunction, not the original outerfunction.
Is there a way to yield result from my custom print directly back to the main function and skip this inceptionesque nightmare?
from __future__ import print_function
import __builtin__
def print(*args, **kwargs):
import builtins
import io
from contextlib import redirect_stdout
builtins.print(*args, **kwargs)
with io.StringIO() as buf, redirect_stdout(buf):
builtins.print(*args, **kwargs)
output = buf.getvalue()
return output
Instead of overriding print, create an object that writes to two different files when you write to it. Something like
# I'm not sure if there are other methods you should override, but
# they would be similar.
class Delegator(io.TextIOBase):
def __init__(self, fh1, fh2):
self.fh1 = fh1
self.fh2 = fh2
def write(self, txt):
self.fh1.write(txt)
self.fh2.write(txt)
def flush(self):
self.fh1.flush()
self.fh2.flush()
sys.stdout = Delegator(sys.stdout, my_other_file)

Python: Indent print output from class

How can I indent the print output on the command line from a class that is called? I can't edit the class file to add tabs to each print().
So I would call the imported class in mypythonthing.py:
print('Calling class')
MyClass()
All the print output would then be indented, or have something prepended to it.
e.g.
$ python mypythonthing.py
$ Running your python script...
$ Calling class
$ > The print output from MyClass is indented
$ > Exiting MyClass
$
Patch the built-in print function to prefix each line with your indentation.
import builtins
def print(*args, **kwargs):
builtins.print(" > ", *args, **kwargs)
If you can put the code that should be indented inside (one or more) functions, then you can use a decorator to wrap these functions.
Then any invocation of print inside these function will be indented.
Also, you will only need to declare this function in your main script, and not anywhere else.
Example -
import builtins
import another # for demo purposes only
# This will override the default `print` function.
# Invoking it as a decorator will automatically perform
# initialisation and cleanup. There is also never a need
# to modify this.
def indent(f):
def closure():
old = builtins.print
builtins.print = lambda x, *args, **kwargs: old("\t>", x, *args, **kwargs)
f()
builtins.print = old
return closure
some_number = "100"
# Example function, note decorator usage.
# This function may **not** take any parameters!
# It may however, use any variables declared before it.
#indent
def indentedStuffGoesHere():
print("Inside `indentedStuffGoesHere`")
print(some_number)
another.Foo().bar()
another.stuff()
print("entering special block")
indentedStuffGoesHere()
print("done")
another.py
def stuff():
print("TESTING stuff")
class Foo:
def bar(self):
print("HELLO FROM FOO")
Output:
entering special block
> Inside `indentedStuffGoesHere`
> 100
> HELLO FROM FOO
> TESTING stuff
done
i think what you might be looking for is textwrap:
textwrap docs
so as an example:
wrapper = textwrap.TextWrapper(width=preferredWidth, subsequent_indent='\t')
message = "asdf" * 50
print wrapper.fill(message)

Categories

Resources