Self Modifying Python? How Can I Redirect All Print Statements Within A Function Without Touching Sys.stdout?
Solution 1:
In Python2.6 (and 2.7), you can use
from __future__ import print_function
Then you can change the code to use the print()
function as you would for Python3
This allows you to create a module global or local function called print which will be used in preference to the builtin function
eg.
from __future__ import print_function
deff(x, print=print):
print(x*x)
f(5)
L=[]
f(6, print=L.append)
print(L)
Solution 2:
Modifying the source code doesn't need to imply breaking backward compatibility.
What you need to do is first replace every print statement with a call to a function that does the same thing:
import sys
def _print(*args, **kw):
sep = kw.get('sep', ' ')
end = kw.get('end', '\n')
file = kw.get('file', sys.stdout)
file.write(sep.join(args))
file.write(end)
def foo():
# print "whatever","you","want"_print("whatever","you","want")
Then the second step is to stop using the _print function directly and make it a keyword argument:
deffoo(_print=_print):
...
and make sure to change all internal function calls to pass the _print function around.
Now all the existing code will continue to work and will use print, but you can pass in whatever _print function you want.
Note that the signature of _print is exactly that of the print function in more recent versions of Python, so as soon as you upgrade you can just change it to use print()
. Also you may get away with using 2to3 to migrate the print statements in the existing code which should reduce the editing required.
Solution 3:
Someone in the sixties had an idea about how to solve this but it requires a bit of alien technology. Unfortunately python has no "current environment" concept and this means you cannot provide context unless specifying it in calls as a parameter.
For handling just this specific problem what about replacing stdout with a file-like object that behaves depending on a thread-specific context ? This way the source code remains the same but for example you can get a separate log for each thread. It's even easy to do this on a specific per-call way... for example:
classMyFakeStdout:
defwrite(self, s):
try:
separate_logs[current_thread()].write(s)
except KeyError:
old_stdout.write(s)
and then having a function to set a logger locally to a call (with
)
PS: I saw the "without touching stdout" in the title but I thought this was because you wanted only some thread to be affected. Touching it while still allowing other threads to work unaffected seems to me compatible with the question.
Post a Comment for "Self Modifying Python? How Can I Redirect All Print Statements Within A Function Without Touching Sys.stdout?"