ccgillett
ccgillett

Reputation: 4561

How to make print() override work "globally"

From How to override python builtins with an import statement I obtained the following code:

from __future__ import print_function
def print(*args, **kwargs):
    .
    . some intervening logic
    .
    return __builtins__.print(*args, **kwargs)

This code works fine, but has module scope. That is, if there are print statements within this file they work as expected, going through the print() function as defined. However, importing it (from foo import *) has no effect within the module that imported it.

If I want to override the print function "globally" how is this best done. Ideally:

from MyOverrides import *
.
.
.
class foo():
    .
    .
    def bar( self ):
        print( "this is my overridden print statement" )

What am I missing about future, overrides, and print() here?

My environment is 2.6 and forward, but not 3.0.

Upvotes: 0

Views: 1195

Answers (2)

ccgillett
ccgillett

Reputation: 4561

Another stackoverflow user provided most of the answer, but then apparently deleted it (?). Here is a working solution. Once again, I recognize this isn't necessarily a best practice, but it can be handy in certain situations.

Module MyOverrides.py:

from __future__ import print_function
import __builtin__

builtin_print = __builtin__.print
def print(*args, **kwargs):
    .
    .... whatever code you need here
    .
    return builtin_print(*args, **kwargs)
__builtin__.print = print

Module test.py:

from __future__ import print_function
from MyOverrides import *
.
.
.

As pointed out by another user, future import needs to happen in every module that intends to use future functionality.

Thanks to user @kindall who answered and then apparently withdrew the answer.

Upvotes: 1

user2357112
user2357112

Reputation: 280898

You can't (and shouldn't) have a global override that turns on a future statement. Since future statements affect the way a Python source file is parsed and compiled, before Python can even tell that MyOverrides defines a print function, all future statements a module uses must be explicit. You can't import a future statement from another module.

The safest way to replace the print function is to explicitly use from __future__ import print_function in all your modules, then import a replacement for print from one of your modules. Don't replace __builtin__.print.

If you want to affect all output to stdout, whether by print statement or print function, anywhere at all, you can replace sys.stdout with a wrapper.

import sys

stdout = sys.stdout

class new_stdout(object):
    def write(*args, **kwargs):
        # do whatever
        stdout.write(*args, **kwargs)

sys.stdout = new_stdout()

However, this is probably a bad idea, and it won't affect print statements or print functions that use an explicit file argument.

Upvotes: 1

Related Questions