Python中的分页输出

36 投票
6 回答
17391 浏览
提问于 2025-04-16 21:44

我正在尝试实现一个类似于 git log 的功能,只有在日志内容达到一定长度时才会分页显示。如果你对 git 不太了解,我的目标基本上是这样的:

python some_script.py | less

在得到一些来自 python2.6/pydoc.py 的分页实现的帮助后,我想出了这个:

import os
text = '...some text...'
pipe = os.popen('less', 'w')
pipe.write(text)
pipe.close()

这个方法效果很好,但 os.popen() 已经不推荐使用了。我考虑过写入一个临时文件,然后用它的路径调用 less,但这似乎不是最理想的解决方案。用 subprocess 实现这个功能可能吗?还有其他的想法吗?

编辑:

我已经让 subprocess 工作了。我能够用 Popen.communicate(text) 将文本变量传递给它,但因为我真的想重定向打印语句,所以我最终选择了这个:

  import os, sys, subprocess, tempfile

  page = True
  if page:
      path = tempfile.mkstemp()[1]
      tmp_file = open(path, 'a')
      sys.stdout = tmp_file
  print '...some text...'
  if page:
      tmp_file.flush()
      tmp_file.close()
      p = subprocess.Popen(['less', path], stdin=subprocess.PIPE)
      p.communicate()
      sys.stdout = sys.__stdout__     

当然,我会把它封装成函数。有人觉得这样有问题吗?

6 个回答

4

在你的代码中明确表达意图是个好主意,这样可以让人一眼看出你使用的是一个特别的打印函数 printc(),而不是标准的打印函数。使用 subprocess.call() 也足够了(你不需要复杂的管道机制)。此外,你可以通过不保存临时文件的名字来节省一个变量:

from __future__ import print_function

import subprocess, tempfile

page = True  # For tests

# Definition of a printc() function that prints to the correct output
if page:
    tmp_file = open(tempfile.mkstemp()[1], 'w')  # No need to store the name in a specific variable
    def printc(*largs, **kwargs):
        if 'file' not in kwargs:  # The code can still use the usual file argument of print()
            kwargs['file'] = tmp_file  # Forces the output to go to the temp file
        print(*largs, **kwargs)
else:
    printc = print  # Regular print

# Main program:

printc('...some text...', 'some more text', sep='/')  # Python3 syntax

# Paging of the current contents of the temp file:
if page:
    tmp_file.flush()  # No need to close the file: you can keep printing to it
    subprocess.call(['less', tmp_file.name])  # Simpler than a full Popen()

这样一来,你就能享受到 Python 3 的 print 函数的灵活性,同时代码也清楚地表明你在做一些特别的打印操作。对于较大的程序来说,这种方式比在代码的某些地方修改“全局”的 sys.stdout 变量要更好。

54

这样做怎么样:

import pydoc
text = '... some text ... '
pydoc.pager(text)

在我的opensuse linux系统上,这段代码会把文本发送到一个分页器(在我这里是'less'),效果和在Python解释器里输入"help(... python命令...)"是一样的。

3

建议使用subprocess.Popen来代替。

查看相关文档

了解subprocess.Popen的更多信息

在os.popen的文档中也有提到这一点。

查看os.popen的文档

撰写回答