我找不到我想要的东西。
我想实时从python函数中获取输出(stdout)。
实际问题是我想在我的UI中使用进度条绘制图表(使用来自sympy的cplot)。参数verbose
使cplot输出到stdout的进度。
sympy.mpmath.cplot(lambda z: z, real, imag, verbose=True)
输出类似于:
0 of 71
1 of 71
2 of 71
...
等等。
我想逐行捕捉,以便我可以制作进度条。 (我意识到如果不实现多线程,这可能是不可能的)。我正在使用python2.7(主要是因为我需要不在python3中的库)
所以,¿我如何实现这一目标?
答案 0 :(得分:0)
您可以通过monkeypatching sys.stdout
捕获标准输出。执行此操作的一种好方法是使用上下文管理器,以便在完成后将其放回(即使代码引发异常)。如果您不使用上下文管理器,请务必使用sys.stdout
块将原始finally
放回原位。
你需要一个类似文件的对象,它接受输入并用它做你想做的事。子类化StringIO
是一个好的开始。这是一个上下文管理器的示例,它捕获stdout和stderr并将它们放在绑定变量的结果中。
class CapturedText(object):
pass
@contextmanager
def captured(disallow_stderr=True):
"""
Context manager to capture the printed output of the code in the with block
Bind the context manager to a variable using `as` and the result will be
in the stdout property.
>>> from tests.helpers import capture
>>> with captured() as c:
... print('hello world!')
...
>>> c.stdout
'hello world!\n'
"""
import sys
stdout = sys.stdout
stderr = sys.stderr
sys.stdout = outfile = StringIO()
sys.stderr = errfile = StringIO()
c = CapturedText()
yield c
c.stdout = outfile.getvalue()
c.stderr = errfile.getvalue()
sys.stdout = stdout
sys.stderr = stderr
if disallow_stderr and c.stderr:
raise Exception("Got stderr output: %s" % c.stderr)
(source)
它的工作原理如docstring所示。您可以将StringIO()
替换为您自己编写进度条的类。
答案 1 :(得分:0)
另一种可能性是monkeypatch sympy.mpmath.visualization.print
,因为cplot
使用print
来打印输出,并使用from __future__ import print_function
。
首先,如果您没有使用Python 3,请确保使用from __future__ import print_function
,否则这将是一个SyntaxError。
然后像
def progressbar_print(*args, **kwargs):
# Take *args and convert it to a progress output
progress(*args)
# If you want to still print the output, do it here
print(*args, **kwargs)
sympy.mpmath.visualization.print = progressbar_print
您可能希望在将其放回的自定义函数中对其进行monkeypatch,因为该模块中的其他函数也可能使用print
。同样,请记住使用上下文管理器或finally
块来执行此操作,以便即使引发异常也会将其放回。
Monkeypatching sys.stdout
绝对是更为标准的做法,但我喜欢这个解决方案,因为它表明将print
作为一个函数实际上可以是有用的。