Интерактивный режим Python PDB прерывается при перенаправлении sys.stdout - PullRequest
1 голос
/ 05 июля 2019

После замены sys.stdout на Tee logger (для перенаправления вывода в файл) PDB больше не работает должным образом. Например, нажатие стрелки вверх производит ^[[A вместо предыдущей команды.

Проблема может быть воспроизведена с помощью этого фрагмента:

import sys
import pdb

class Tee(object):
    def __init__(self, name, mode):
        self.file = open(name, mode)
        self.stdout = sys.stdout
        sys.stdout = self
    def __del__(self):
        sys.stdout = self.stdout
        self.file.close()
    def write(self, data):
        self.file.write(data)
        self.stdout.write(data)
    def flush(self):
        self.file.flush()

sys.stdout = Tee('test.txt', 'w')
pdb.set_trace()

Есть ли способ заменить sys.stdout без поломки PDB?

1 Ответ

0 голосов
/ 06 июля 2019

(1) Вы не можете иметь интерактивность на выходе tee'd, потому что это обычный поток, а не терминал.Терминал позволяет выполнять множество задач: позиционировать курсор, стирать содержимое, читать клавиши, отображать нажатия клавиш на экране и т. Д. Обычный файл на диске не может делать все эти вещи, поэтому pdb не можетделать эти вещи в интерактивном режиме.Вы можете проверить, что sys.stdout.isatty() возвращает True, если вы запускаете REPL.

(2) Конечно, вы можете изменить каждый print вызов функции в вашем коде для записи в stdout и для любого файла, который вы хотите, потому что вы можете переопределить print.Это работает в Python 3 и в Python 2.7, если вы from __future__ import print.Тогда вы можете делать такие вещи:

system_print = print  # preserve the original.

def print_also_to(other_file):
  def tee_print(*args, **kwargs):
    system_print(*args, **kwargs)  # Normally prints to stdout.  
    system_print(*args, **kwargs, file=other_file)  # Write a copy.
  return tee_print

print = print_also_to(open('/tmp/copy-of-stdout'))  # A crude example.

print("Hello world!")  # Unmodified code.

С print заявлениями ваша ситуация хуже.Используйте strace в Linux или DTrace в macOS, чтобы записать запись в стандартный вывод (и другие места) и перенаправить его в файл при запуске процесса:

strace -e trace=write -o writes.txt python your-script.py

Это будетнапишите в файл что-то вроде write(1, 'Hello world!').Вам нужно было бы проанализировать его и реконструировать вывод в stdout (1) специально для получения реальной копии вывода.

Полагаю, что интерактивный режим pdb также будет работать при этом;по крайней мере, Python REPL отлично работает под strace.

...