Python – обнаруживает, когда мой объект записывается в stdout?

У меня довольно необычная просьба, я думаю … Я объясню, почему после того, как я объясню, что.

Какие

Я хочу, чтобы каждый раз, когда мой объект записывался в stdout, я мог выполнять побочные эффекты в это время. Так, например, когда я печатаю:

sys.stdout.write(instance_of_my_class) 

он должен выполнять побочные эффекты. Я сделал свой класс подклассом str и __call__ , __unicode__ , __str__ , __repr__ , index , __repr__ , encode , format , __format__ , __getattribute__ , __getitem__ и __len__ чтобы каждый из них __len__ заявление, указывающее, что они , но кажется, что sys.stdout.write вызывает ни одного из них для печати объекта.

Обратите внимание, что я специально говорю о sys.stdout.write а не, например, print – я обнаружил, что print вызывает __str__ на том, что он задан.

Зачем

Этот вопрос продолжается, когда ответ на цветную подсказку Python в Windows? прекращено.

Я обнаружил, что каждый раз, когда python должен отображать интерактивное приглашение, он вызывает __str__ на sys.ps1 и sys.ps2 , а затем сохраняет результаты, которые будут отображаться в командной строке. Это означает, что любые побочные эффекты в sys.ps2.__str__ вызываются сразу после sys.ps1.__str__ , но я хочу, чтобы они sys.ps1.__str__ , пока не sys.ps2 время отображать sys.ps2 .

Поэтому вместо того, чтобы возвращать str в sys.ps2.__str__ , я возвращаю свой подкласс str , который, я надеюсь, каким-то образом сможет поймать, когда на sys.stdout.write вызывается sys.stdout.write .

2 Solutions collect form web for “Python – обнаруживает, когда мой объект записывается в stdout?”

Почему не monkeypatch stdout.write?

 stdoutRegistry = set() class A(object): def __init__(self): self.stdoutRegistry.add(self) def stdoutNotify(self): pass original_stdoutWrite = sys.stdout.write def stdoutWrite(*a, **kw): if a in stdoutRegistry: a.stdoutNotify() original_stdoutWrite(*a, **kw) sys.stdout.write = stdoutWrite 

Интригующая проблема! Моя первая догадка заключается в том, что sys.stdout.write не вызывает метод __str__ потому что ваш объект уже является str (или, по крайней мере, его подклассом, который достаточно хорош для всех целей и задач) … поэтому никаких методов литья необходимы.

Дальнейшее исследование предполагает, что sys.stdout.write действительно никогда не хочет называть метод __str__

Подкласс

С небольшой интроспекцией вы можете узнать, какие методы вашего подкласса str вызывают sys.stdout.write (ответа не так много):

 class superstring(str): def __getattribute__(self, name): print "*** lookup attribute %s of %s" % (name, repr(self)) return str.__getattribute__(self, name) foo = superstring("UberL33tPrompt> ") sys.stdout.write(foo) 

Запуск в среде Unicode (Python 2.7, iPython notebook), это печатает:

 *** lookup attribute __class__ of 'UberL33tPrompt> ' *** lookup attribute decode of 'UberL33tPrompt> ' UberL33tPrompt> 

Это похоже на kludge-y, но вы можете переопределить метод decode подкласса для выполнения желаемых побочных эффектов.

Однако в среде, отличной от Юникода , нет поиска атрибутов .

Подборщик

Вместо того, чтобы использовать подкласс str , возможно, вам нужна какая-то «обертка» вокруг str . Вот уродливый исследовательский хак, который создает класс, который делегирует большинство своих атрибутов str , но который не является строго его подклассом:

 class definitely_not_a_string(object): def __init__(self, s): self.s = s def __str__(self): print "*** Someone wants to see my underlying string object!" return self.s def decode(self, encoding, whatever): print "*** Someone wants to decode me!" return self.s.decode(encoding, whatever) def __getattribute__(self, name): print "*** lookup attribute %s of %s" % (name, repr(self)) if name in ('s', '__init__', '__str__', 'decode', '__class__'): return object.__getattribute__(self, name) else: return str.__getattribute__(self, name) foo = definitely_not_a_string("UberL33tPrompt> ") sys.stdout.write(foo) 

В среде Unicode это дает в основном те же результаты:

 *** lookup attribute __class__ of <__main__.definitely_not_a_string object at 0x00000000072D79B0> *** lookup attribute decode of <__main__.definitely_not_a_string object at 0x00000000072D79B0> *** Someone wants to decode me! *** lookup attribute s of <__main__.definitely_not_a_string object at 0x00000000072D79B0> UberL33tPrompt> 

Однако, когда я запускаю среду, отличную от Unicode, definitely_not_a_string выдает сообщение об ошибке:

 TypeError: expected a character buffer object 

… это показывает, что метод .write подходит к интерфейсу буфера уровня C, когда ему не нужно выполнять декодирование Unicode.

Мое заключение

Кажется, что переопределение метода decode является возможной ошибкой в средах Unicode, поскольку sys.stdout.write вызывает этот метод, когда ему нужно декодировать str в Unicode.

Тем не менее, в средах, отличных от Unicode, кажется, что .write не выполняет каких-либо поисков атрибутов, а просто переходит к протоколу символьного буфера уровня C, поэтому нет способа перехватить его доступ из кода Python. Действительно, help(sys.stdout.write) проверяет, что это встроенная функция (она написана на C, а не на Python).

  • Python: «subprocess.Popen» проверить успех и ошибки
  • Захват stdout из скрипта в Python
  • Захват вывода из буферизованной программы StdOut
  • вывод трубопровода подпроцесса. Открытие файлов
  • Доступ к распечатанному выходу вызова функции
  • Необходимо избегать взаимоблокировки подпроцесса без связи
  • Как перенаправить в реальном времени STDOUT из импортированного модуля в Tkinter Text Widget в python?
  • Как я могу захватить вывод stdout дочернего процесса?
  •  
    Interesting Posts for Van-Lav

    Scipy – 3d griddata – Почему нужно вводить аргумент griddata xi для кортежа?

    Переименуйте оси в графическом трехмерном тексте

    Где я должен поместить файл .pdbrc в окна, чтобы он был глобально видимым?

    Каков самый чистый способ остановить работу многопроцессора python, подключенного к очереди в бесконечном цикле?

    Бизнес-пример для предприятия Python

    Python устанавливает панды

    как открыть хром в режиме инкогнито от Python

    Интерактивный граф Matplotlib, встроенный в PyQt

    Как открыть файл через python

    Является ли Google App Engine правильным для меня?

    строка для преобразования списка в python?

    Скрипт Python не запускается через CGI на Apache2

    Значение по умолчанию для параметра DateTimeField для миграции юга в проекте Django с поддержкой активного часового пояса

    Геометрическая деформация изображения в python

    Несколько вопросов о выражениях генераторов и эффективных скоростях

    Python - лучший язык программирования в мире.