2015-03-28 3 views
3

У меня есть несколько объектов, которые мне нужно распечатать на терминал (для отладки). Нормальная функция print почти идеальна, за исключением того, что некоторые объекты слишком велики, поэтому print создаст миллионы строк вывода. Я хотел бы создать функцию, которая делает то, что делает print, за исключением того, что вывод усечен после предопределенного количества символов, заменяя остальные на ....Ограничение вывода на печать

Каков хороший способ сделать это?

Обратите внимание, что производительность является проблемой, поэтому в идеале я бы предпочел не сохранять строку размера гигабайта, а затем взять из нее первые несколько символов; Аналогично, pprint - это немного проблема, поскольку он сортирует ключи в словарях (и с миллионами ключей занимает некоторое время).

Пример:

obj = [ [1, 2, 3], list(range(1000000)) ] 
my_print(obj, 20) 
# should output: 
# [[1, 2, 3], [0, 1, 2... 

Python 3, если это имеет значение.

+1

Если у вас есть словари с гнездом, возможно, ['pprint.pprint'] (https://docs.python.org/3.4/library/pprint.html) с набором параметров' depth' поможет? – myaut

+0

@myaut это не совсем то, что я искал, но это действительно полезно! Благодаря! – max

+4

Вы можете определить свое собственное представление с помощью ['reprlib'] (https://docs.python.org/3.4/library/reprlib.html). – m0nhawk

ответ

7

Модуль reprlib (только для Python 3.x), предложенный @ m0nhawk, сделан именно для этой цели.Вот как вы будете использовать его:

Если вы хорошо с пределах по умолчанию, вы можете просто использовать reprlib.repr(obj):

import reprlib 

obj = [[1, 2, 3], list(range(10000))] 

print(reprlib.repr(obj)) 

Выход:

[[1, 2, 3], [0, 1, 2, 3, 4, 5, ...]] 

Для того, до настройте available limits, просто создайте экземпляр reprlib.Repr и установить соответствующий экземпляр атрибуты:

r = reprlib.Repr() 
r.maxlist = 4  # max elements displayed for lists 
r.maxstring = 10 # max characters displayed for strings 

obj = [[1, 2, 3], list(range(10000)), 'looooooong string', 'a', 'b', 'c'] 

print(r.repr(obj)) 

Выход:

[[1, 2, 3], [0, 1, 2, 3, ...], 'lo...ing', 'a', ...] 

Если вы имеете дело с последовательностью объектов, которые относятся к себе, вы можете использовать Repr.maxlevel, чтобы ограничить глубину рекурсии :

lst = [1, 2, 3] 
lst.append(lst) # oh my! 

r = reprlib.Repr() 
r.maxlevel = 5 # max recursion depth 

print(r.repr(lst)) 

Выход:

[1, 2, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [...]]]]]] 

Обратите внимание, что reprlib.repr()возвращает строка, но не print его (если вы не в интерактивной консоли, где результат каждого выражения вы вводите получает оценку и его представление отображается).

2

Почему бы просто не сделать простую обертку обрезки над функцией print?

def my_print(obj, depth): 
    print(str(obj)[:depth]) 

print делает то же самое, что str перед записью в выходной поток. Итак, что вы хотите сделать, это сделать это кастинг рано, прежде чем передавать его в печать, а затем отрезать кусок его, который имеет максимальный размер того, что вы хотите.

Python slicing является изящным, поэтому строчный срез, как 'xyz'[:30000], оценивается просто 'xyz', а не поднимает ошибку.

+1

Это будет работать отлично, за исключением того, что все равно потребуется навсегда запустить. У меня есть словари с сотнями тысяч ключей, значениями которых являются списки с сотнями предметов. Преобразование их в 'str' займет очень много времени, поэтому в идеале я бы хотел этого избежать. – max

+0

@max Я думаю, что вызов 'str' в значительной степени неизбежен. Вы можете попробовать изменить, что делает 'str', просмотрев систему специальных методов Python и' __str__': https://docs.python.org/3/reference/datamodel.html#object.__str__ Однако большая проблема в том, что вы не может изменять атрибуты встроенных типов, таких как 'dict'. Я думаю, вы могли бы зависеть от реализации своего собственного класса-оболочки над dict, а затем переопределения своей функции '__str__' своим собственным. – Shashank

Смежные вопросы