перегрузка печати питона - PullRequest
40 голосов
/ 15 февраля 2009

Могу ли я перегрузить функцию print и вызвать нормальную функцию изнутри? Что я хочу сделать, так это после определенной строки, которую я хочу, чтобы print позвонил моему print, который будет вызывать обычный print, и записать копию в файл.

Также я не знаю, как перегрузить print. Я не знаю, как сделать аргументы переменной длины. Скоро я посмотрю, но перегруженный печатный питон только что сказал мне, что я не могу перегрузить print в 2.x , что я и использую.

Ответы [ 9 ]

58 голосов
/ 11 апреля 2012

Для тех, кто просматривает ранее датированные ответы, начиная с версии "Python 2.6", есть новый ответ на оригинальный вопрос автора.

В Python 2.6 и выше вы можете отключить оператор печати в пользу функции печати, а затем переопределить функцию печати своей собственной функцией печати:

from __future__ import print_function
# This must be the first statement before other statements.
# You may only put a quoted or triple quoted string, 
# Python comments, other future statements, or blank lines before the __future__ line.

try:
    import __builtin__
except ImportError:
    # Python 3
    import builtins as __builtin__

def print(*args, **kwargs):
    """My custom print() function."""
    # Adding new arguments to the print function signature 
    # is probably a bad idea.
    # Instead consider testing if custom argument keywords
    # are present in kwargs
    __builtin__.print('My overridden print() function!')
    return __builtin__.print(*args, **kwargs)

Конечно, вам нужно учитывать, что эта функция печати на данный момент является только модульной. Вы можете переопределить __builtin__.print, но вам нужно сохранить исходный __builtin__.print; вероятнее всего, взламывает пространство имен __builtin__.

31 голосов
/ 15 февраля 2009

Перегрузка print - это конструктивная особенность Python 3.0, позволяющая решить проблему отсутствия у вас возможности сделать это в Python 2.x.

Однако вы можете переопределить sys.stdout. ( пример .) Просто назначьте его другому файлообразному объекту, который делает то, что вы хотите.

В качестве альтернативы, вы можете просто передать свой скрипт через команду unix tee. python yourscript.py | tee output.txt будет печатать как в stdout, так и в output.txt, но при этом будут получены все выходные данные.

10 голосов
/ 27 марта 2009

Я столкнулся с той же проблемой.

Как насчет этого:

class writer :
    def __init__(self, *writers) :
        self.writers = writers

    def write(self, text) :
        for w in self.writers :
            w.write(text)

import sys

saved = sys.stdout
fout = file('out.log', 'w')
sys.stdout = writer(sys.stdout, fout)
print "There you go."
sys.stdout = saved
fout.close()

Это сработало как очарование для меня. Взято из http://mail.python.org/pipermail/python-list/2003-February/188788.html

8 голосов
/ 23 марта 2013
class MovieDesc:
    name = "Name"
    genders = "Genders"
    country = "Country"

 def __str__(self):
#Do whatever you want here
        return "Name: {0}\tGenders: {1} Country: {2} ".format(self.name,self.genders,self.country)

)
3 голосов
/ 15 февраля 2009

Хотя вы не можете заменить ключевое слово print (в Python 2.x print - это ключевое слово), обычной практикой является замена sys.stdout, чтобы сделать что-то похожее на переопределение print; например, с экземпляром StringIO.StringIO. Это будет захватывать все напечатанные данные в экземпляре StringIO, после чего вы можете манипулировать им.

2 голосов
/ 15 февраля 2009

В Python 2.x вы не можете, потому что print - это не функция, это утверждение. В Python 3 печать - это функция, поэтому я полагаю, что она может быть переопределена (хотя я и не пробовал).

1 голос
/ 04 апреля 2016

Для очень простого примера, начиная с Python3.4 (не тестировался с более старыми версиями), это хорошо работает для меня (размещено в верхней части модуля):

def dprint(string):
  __builtins__.print("%f -- %s" % (time.time(), string))

print = dprint

Обратите внимание, это работает только в том случае, если строковым параметром является str ... YMMV

1 голос
/ 22 февраля 2014

просто подумал, что добавлю свою идею ... подходило для моих целей - запустить sthg в Eclipse, а затем запустить из (Windows) CLI без получения исключений кодирования с каждым оператором печати. Что бы вы ни делали, не делайте EncodingStdout подклассом файла класса: строка «self.encoding = encoding» приведет к тому, что атрибут кодирования будет None!

NB. Одна вещь, которую я обнаружил в течение дня, пытаясь разобраться с этим, заключается в том, что исключение кодирования возникает перед тем, как перейти к «печати» или «записи»: это когда параметризованная строка (т.е. "% (" blip "," blap ")) создается ... что ??? "рамки"?

class EncodingStdout( object ):
    def __init__( self, encoding='utf-8' ):
        self.encoding = encoding

    def write_ln( self, *args ):
        if len( args ) < 2:
            sys.__stdout__.write( args[ 0 ] + '\n' )
        else:
            if not isinstance( args[ 0 ], basestring ):
                raise Exception( "first arg was %s, type %s" % ( args[ 0 ], type( args[ 0 ]) ))
            # if the default encoding is UTF-8 don't bother with encoding
            if sys.getdefaultencoding() != 'utf-8':
                encoded_args = [ args[ 0 ] ]
                for i in range( 1, len( args )):
                    # numbers (for example) do not have an attribute "encode"
                    if hasattr( args[ i ], 'encode' ):
                        encoded_args.append( args[ i ].encode( self.encoding, 'replace' ) )
                    else:
                        encoded_args.append( args[ i ])
                args = encoded_args
            sys.__stdout__.write( args[ 0 ] % tuple( args[ 1 : ] ) + '\n' )
        # write seems to need a flush
        sys.__stdout__.flush()

    def __getattr__( self, name ):
        return sys.__stdout__.__getattribute__( name )

print "=== A mondodod %s %s" % ( "été", "pluviôse, irritée contre la ville entière" ) 


sys.stdout = EncodingStdout()
sys.stdout.write_ln( "=== B mondodod %s %s", "été", "pluviôse, irritée contre la ville entière" )

# convenience method
def pr( *args ):
    sys.stdout.write_ln( *args )

pr( "=== C mondodod %s %s", "été", "pluviôse, irritée contre la ville entière" )
1 голос
/ 30 ноября 2009

Я ответил на тот же вопрос на другой вопрос SO

По сути, самое простое решение - просто перенаправить вывод в stderr следующим образом, в файле конфигурации wsgi.

sys.stdout = sys.stderr
...