2013-02-20 2 views
4

Im пытается понять, как создать пользовательскую функцию печати. (с использованием Python 2.7)python: change sys.stdout print to custom print function

import sys 
class CustomPrint(): 
    def __init__(self): 
     self.old_stdout=sys.stdout #save stdout 

    def write(self, text): 
     sys.stdout = self.old_stdout #restore normal stdout and print 
     print 'custom Print--->' + text 
     sys.stdout= self # make stdout use CustomPrint on next 'print' 
         # this is the line that trigers the problem 
         # how to avoid this?? 


myPrint = CustomPrint() 
sys.stdout = myPrint 
print 'why you make 2 lines??...' 

Код выше принтами это утешать:

>>> 
custom Print--->why you make 2 lines??... 
custom Print---> 

>>> 

и я хочу, чтобы напечатать только одну строку:

>>>  
1custom Print--->why you make 2 lines??... 
>>> 

Но не могу понять, как сделайте эту обычную работу печати, я понимаю, что есть какая-то рекурсия, которая запускает второй вывод на консоль (я использую self.write, чтобы назначить stdout для self.write!)

Как я могу сделать эту работу? или мой подход просто совершенно неправильный ...

+0

Связанный: [Перенаправить stdout в файл в Python?] (Http://stackoverflow.com/q/4675728/4279) – jfs

ответ

2

Это не рекурсия. Случается, что ваша функция write вызывается дважды, один раз с текстом, который вы ожидаете, второй раз с '\n'. Попробуйте это:

import sys 
class CustomPrint(): 
    def __init__(self): 
     self.old_stdout=sys.stdout 

    def write(self, text): 
     text = text.rstrip() 
     if len(text) == 0: return 
     self.old_stdout.write('custom Print--->' + text + '\n') 

Что я делаю в приведенном выше коде, я добавить символ новой строки к тексту принятого в первом вызове, и убедитесь, что на второй вызов, сделанное заявление печати, один предназначен для печати новая строка, ничего не печатает.

Теперь попробуйте закомментировать первые две строки и посмотреть, что происходит:

def write(self, text): 
     #text = text.rstrip() 
     #if len(text) == 0: return 
     self.old_stdout.write('custom Print--->' + text + '\n') 
+0

Спасибо, его работа вроде как должна :) не знала, что \ n был добавлен на второй проход! sys.stderr.write (":". join ("{0: b}". format (ord (c)) для c в тексте)) даже добавил эту строку, чтобы убедиться, и ваш правый ^^ – andsoa

+1

есть небольшой проблема при использовании запятой, отделенной печатью: 'print var1, var2' По-видимому, запятая вызывает печать для каждого 'var' и подавляет добавление '\ n' в предыдущем «var»! Это можно решить, добавив tmp var в класс customPrint, который хранит текст, и только печатает, когда текст заканчивается на «\ n» – andsoa

+0

@andsoa Ok, спасибо, что поделились этим – piokuc

1

Как насчет того, чтобы делать from __future__ import print_function. Таким образом вы будете использовать функцию печати Python3 вместо инструкции print из Python2. После этого вы можете переопределить функцию печати:

def print(*args, **kwargs): 
    __builtins__.print("Custom--->", *args, **kwargs) 

Существует поймать, однако, вы должны будете начать использовать функцию печати.

+0

Это сработает, но в моем случае мне нужно изменить вывод вывода некоторых классов, написанных с помощью python 2.7 print:/ – andsoa

3

Одним из решений может быть использовать менеджер контекста, если он локализован.

#!/usr/bin/env python 
from contextlib import contextmanager 
################################################################################ 
@contextmanager 
def no_stdout(): 
    import sys 
    old_stdout = sys.stdout 
    class CustomPrint(): 
     def __init__(self, stdout): 
      self.old_stdout = stdout 

     def write(self, text): 
      if len(text.rstrip()): 
       self.old_stdout.write('custom Print--->'+ text) 

    sys.stdout = CustomPrint(old_stdout) 

    try: 
     yield 
    finally: 
     sys.stdout = old_stdout 
################################################################################ 
print "BEFORE" 
with no_stdout(): 
    print "WHY HELLO!\n" 
    print "DING DONG!\n" 

print "AFTER" 

выше производит:

BEFORE 
custom Print--->WHY HELLO! 
custom Print--->DING DONG! 
AFTER 

код нужно будет прибирать особ. вокруг того, что класс должен делать WRT, устанавливая stdout обратно в то, что было.

+0

, спасибо, что разделили это элегантное решение! – andsoa