Python中的分页输出
我正在尝试实现一个类似于 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