Python - 如何查看超出屏幕范围的输出?

18

我想说,我正在寻找一种解决问题的方法,即查看超出屏幕范围的输出。例如,range(100)将在高度为30的终端中显示最后约30行。

我只是想获得正确方向的指导,想知道你们如何解决这个问题。

当你遇到希望能方便地滚动查看一些大量输出的情况时,你会怎么做?

最佳答案

使用终端的滚动缓冲区。

如果您使用GNU Screen,则可以在HOME/.screenrc中设置defscrollback 1000或任何其他数字。

使用Ctrl-a,[进入复制模式。

j -    Move the cursor down by one line
k -    Move the cursor up by one line
C-u -  Scrolls a half page up.
C-b -  Scrolls a full page up.
C-d -  Scrolls a half page down.
C-f -  Scrolls the full page down.
G -    Moves to the specified line 

最棒的部分是在复制模式下使用/进行正向搜索,?进行反向搜索。

超级方便。

谢谢!


原问题:

Python中类似于bash less命令的相应命令是什么?

LongString | less 

有没有类似的Python工具?我觉得我经常可以使用它,但最终只能选择其他解决方案。

所谓的“长输出”是指任何生成的输出行数超过我的屏幕。例如1000个打印消息、一个字典、一个大字符串、range(1000)等。

我的Google搜索无果。


1
我不太确定你所说的“for Python”是什么意思。在什么情况下,less 对你来说无法工作? - Greg Hewgill
1
我正在查看myobject.log,它是一个非常长的字符串。我想在Python解释器中能够滚动查看它。我应该怎么做? - Yuji 'Tomita' Tomita
@Yuji:你能打开另一个窗口吗?你能在另一个窗口中使用less吗?有什么阻止你这样做吗?你知道Python的help函数使用less吗? - S.Lott
@Yuji - 你是在谈论在解释器中工作时进行输出,还是在运行bash(或其他)命令行上运行脚本产生的输出? - detly
2
@detly 我指的是解释器。我经常在那里,会遇到一些附加在我正在处理的对象上的数据太长了,但我仍然希望能快速浏览一下它们。 - Yuji 'Tomita' Tomita
显示剩余4条评论
9个回答

10

仅仅为了好玩 :o)

Python 2的原始版本:

class Less(object):
    def __init__(self, num_lines):
        self.num_lines = num_lines
    def __ror__(self, other):
        s = str(other).split("\n")
        for i in range(0, len(s), self.num_lines):
            print "\n".join(s[i: i + self.num_lines])
            raw_input("Press <Enter> for more")

less = Less(num_lines=30)  
"\n".join(map(str, range(100))) | less

Python3版本:

class Less(object):
    def __init__(self, num_lines):
        self.num_lines = num_lines
    def __ror__(self, other):
        s = str(other).split("\n")
        for i in range(0, len(s), self.num_lines):
            print(*s[i: i + self.num_lines], sep="\n")
            input("Press <Enter> for more")

less = Less(num_lines=30)  
"\n".join(map(str, range(100))) | less

4
当然,你的意思是 class More :) - badp
1
非常棒的答案,这是一个简短而优雅的代码片段,可以放置在任何脚本中。它也是跨平台的(已测试在Windows 7上),不需要任何外部库。 - gaborous
这很不错,但一个缺点在于它是同步的;在等待用户完成滚动输出时,您的程序会停止。 - Nate Glenn
@NateGlenn 这似乎更适用于Python交互式控制台而不是实际脚本,而且控制台本身就是同步的。 - nog642

4
如果您想在交互式Python会话中执行此操作,应使用允许您向上滚动的终端仿真。我认为大多数仿真器都可以。
如果您正在使用实际终端,或者没有终端仿真器选择,也许您可以使用GNU screen。
(如果您使用Windows,则可以更改屏幕缓冲区大小以允许向上滚动到9999行)。
如果您需要将此用于程序输出,则可以尝试使用curses模块自己实现滚动。

这听起来像是一个很好的解决方案!扇自己一巴掌!我只需要在屏幕上将我的滚动缓冲区提高很多。哦,明天会试试这个。无法感谢你的帮助。 - Yuji 'Tomita' Tomita
将我的GNU Screen滚动缓冲区提高到10k:)可以方便地向上导航半页、整页等。感谢itsadok的答案!我会写一篇文章,希望其他人也会发现它有用。似乎很难在不被攻击更好的编码实践、不要首先陷入这种情况等方面提出这个问题。你非常有帮助。 - Yuji 'Tomita' Tomita

2

是的,有一种方法,而且非常简单,所以没有具体描述。假设您有一个很长的列表,并且只想查看开头:

>>> lst = range(1000)   # let's make list of thousand elements
>>> lst[:100]           # i want to see just the first 100
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>> lst[100:201]        # ok, now the 2nd hundred 
[100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200]
>>> lst[-100:]          # and now just the last 100, pretty please?
[900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999]

相同的[]切片对于字符串也适用。对于字典,你可以通过一些方法来欺骗,比如使用str()将其转换为字符串,然后使用相同的切片显示 :-)

1
假设您正在使用Python编写程序,其作用仅是漂亮地打印一些东西。输出在prettiest_print_ever中。您已经使用奇怪的技巧导入fcntltermiosstruct等来获取终端大小,以便您可以使用终端的全部宽度(如果有的话);这也给出了屏幕高度,因此使用它是有意义的。(这也意味着您已经放弃了跨平台兼容性的任何假装。)
当然,您可以重新发明轮子,或者像其他程序一样依赖于less(例如git diff)。这应该是解决方案的概要:
def smart_print(prettiest_print_ever, terminal_height = 80):
  if len(prettiest_print_ever.splitlines()) <= terminal_height:
    #Python 3: make sure you write bytes!
    sys.stdout.buffer.write(prettiest_print_ever.encode("utf-8"))
  else
    less = subprocess.Popen("less", stdin=subprocess.PIPE)
    less.stdin.write(prettiest_print_ever.encode("utf-8"))
    less.stdin.close()
    less.wait()

那个使用 subprocess 和 less 的最后一位正是我所需要的。 - GaryBishop

0

如果你在ipython中工作,你可以在交互式的Python会话中执行shell命令。这意味着你只需要执行以下操作:

In [1]: less myfile.txt

我也非常喜欢能够使用向上和向下箭头获取以前的命令,并通过执行类似以下操作来获取以前命令的输出

In [33]: print cos(Out[7]*pi/180)

谢谢!我喜欢使用ipython并能够使用命令。我经常使用它,也喜欢能够在其中编辑文件。我的输出会显示在解释器中,所以没有文件名。我想我可以将输出保存为文件 :P 我能直接将输出传输到less吗? - Yuji 'Tomita' Tomita
我在ipython中很少使用编辑命令,也不确定如何命名文件。我倾向于使用Eclipse或gedit编辑Python文件,并在想要交互式地检查代码工作方式时使用ipython。 - procrastinate_later

0
如果你的数据可以被 JSON 序列化,你可以尝试这样做。
import simplejson
print simplejson.dumps({'shipping-line': {'price': '0.00', 'code': 'Local Pickup (Portland, OR)', 'title': 'Local Pickup (Portland, OR)'}}, indent=4)

输出将会看起来像这样

{
    "shipping-line": {
        "price": "0.00", 
        "code": "Local Pickup (Portland, OR)", 
        "title": "Local Pickup (Portland, OR)"
    }
}

这是专门用于调试和查看实际内容的工具......以易读的格式呈现。

编辑:

如果您的屏幕限制为25行..........

import simplejson
data = simplejson.dumps({'shipping-line': {'price': '0.00', 'code': 'Local Pickup (Portland, OR)', 'title': 'Local Pickup (Portland, OR)'}}, indent=4)

cnt = 0

for line in data.split('\n'):
    cnt+=1
    print line
    raw_input() if cnt%25==0 else None

嗨 Shah,谢谢!但如果输出内容是现在的10倍长,不适合我的终端怎么办?输出会滚动到底部。我的解决方法只能是将其切片吗? - Yuji 'Tomita' Tomita

0

在Shell中运行less和Python之间有一个根本性的区别:Python是一种编程语言,而less是一个程序。

Bash知道控制台中的行数,less可以查询它(以及其他一些东西),但Python本身不能,它是一种语言,对其环境是不可知的(这留给库来处理)。

除此之外,less遵循自己的一些标准。插入符号所在的行会被移动到顶部,它会使用termcap,它在概念上属于操作系统工具,并且即使没有完成文件的读取,它也会发送输出。

如果你想的话,可以用Python编写less,或者从Python脚本内部运行它,但它的功能比单个文件的方法更多(也太特定了)。


谢谢,我感谢你的回答。我应该重新表达一下,我的问题是如何查看大于屏幕的输出,所以迄今为止,似乎我需要编写自己的代码将各种输出拆分成块,但它似乎是应该存在的东西。 - Yuji 'Tomita' Tomita

-1

编写自己的代码很容易:

def less(s, line_count = 5):
    lines = []
    for i, line in enumerate(s.split('\n'), 1):
        lines.append(line)
        if (i % line_count) == 0:
            yield '\n'.join(lines)
            lines = []

    if lines:
        yield '\n'.join(lines)

嗨,克里斯,谢谢!我想过一两种方法来分割各种输出,但似乎这是如此常见的事情,应该内置在其中。我很惊讶我找不到相关信息。 - Yuji 'Tomita' Tomita

-2
你遇到需要方便地滚动查看大量输出的情况时,你会怎么做?
1. 不要创建大量输出。使用函数来总结或显示选定的细节。 2. 简化应用程序以避免首先创建大量输出。 3. 集中注意力以避免大量输出。 4. 通常要避免大量输出。
避免大量输出似乎比围绕着我从未关心过的东西进行纠缠更简单。

2
嗨S,谢谢你的回复,但我特别指的是那些我确实遇到大量输出的小情况。通常,我知道字典中应该有什么,所以大量输出不是问题。但如果每个满月一次,我会处于这样一种情况:我在Python中,我打开了一个数据库条目,其中包含一个大的条目,我宁愿不去PGSQL。我希望你们能帮助解决真正的问题,而不是认为我的问题无效。 - Yuji 'Tomita' Tomita
1
@Yuji:抱歉,但您没有理解重点。您的问题是无效的。您有Python。您可以编写代码。因此,请编写代码。请编写代码来操作/汇总/过滤/提取您的数据。请只需编写代码--这就是您使用Python的原因。 - S.Lott
2
解决方案是在您使用的任何终端中提高回滚缓冲区并向上滚动:P 耶。零编码,超级方便,正是我要寻找的答案类型。对于“当您希望能够滚动查看一些大型输出时该怎么办”的答案是“滚动查看大型输出”:D 谢谢大家。 - Yuji 'Tomita' Tomita
1
我真的不知道你为什么这么争论。我不需要用大杀器来对付小问题,我只是在寻找一种尽可能简单和方便的解决方案:我已经找到了。谢谢! - Yuji 'Tomita' Tomita
1
对我来说,我对数据了解得越少,滚动速度就越快(3个按键+每页1个)。我对数据了解得越多,排序/切片速度就越快。两者都有其适用的场合。 至于是否应该超越编程语言的限制?我们本质上是不同的信仰,只能选择离开或互相残杀。我会选择前者。 - Yuji 'Tomita' Tomita
显示剩余12条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接