目前我有一个调用另一个python文件的flask
项目。我完全清楚这种方式有点糟糕,因此,我希望将其换成函数调用,同时保持打印到网站上的打印。
def get_Checks():
root = request.url_root
def func():
yield ("Inicio <br>")
with subprocess.Popen(r"python somefile.py", stdout=subprocess.PIPE, bufsize=1,
universal_newlines=True) as p:
for line in p.stdout:
yield (line + "<br>")
return Response(func())
我尝试直接用函数替换文件调用,但它只是将它打印到控制台。
我非常感谢您提供的任何帮助。
答案 0 :(得分:1)
一种简单的方法是暂时将sys.stdout
更改为类似文件的对象,调用该函数,然后恢复sys.stdout
。输出将在类文件对象中可用。
这是一个工作的Flask应用程序,演示了该方法:
import sys
from io import StringIO
from flask import Flask, request, Response
import somefile
app = Flask(__name__)
@app.route("/")
def hello():
def func():
yield ("Inicio <br>")
try:
_stdout = sys.stdout
sys.stdout = output = StringIO()
somefile.main()
output.seek(0)
for line in output:
sys.stdout = _stdout
yield '{}<br>'.format(line.rstrip())
sys.stdout = output
finally:
sys.stdout.close() # close the StringIO object
sys.stdout = _stdout # restore sys.stdout
return Response(func())
if __name__ == "__main__":
app.run()
这里使用io.StringIO
对象来收集函数产生的标准输出,然后从该对象产生线。 finally
确保之后恢复原始sys.stdout
。 yield
语句有一些额外的复杂性,因为yield
将控制返回到调用代码,如果调用者也想打印到stdout,则必须恢复stdout。
假设somefile.py
中的函数是“main”函数,并且它的调用由if __name__ == '__main__':
测试保护,如下所示:
def main():
for i in range(10):
print(i)
if __name__ == '__main__':
main()
答案 1 :(得分:0)
假设您要抓取的所有打印都在同一模块中完成,您可以修补其他模块的print
功能。在下面的示例中,我使用上下文管理器在抓取完成后恢复原始打印功能。
这是mod1
,具有行为不当功能的模块。
def bogus_function():
print('Hello World!')
print('Line 2')
这是mod2
,模块使用mod1.bogus_function()
import io
import functools
import contextlib
import mod1
@contextlib.contextmanager
def grab_stdout(module, fd):
def monkey_print(*args, **kwargs):
kwargs['file'] = fd
print(*args, **kwargs)
setattr(module, 'print', monkey_print)
try:
yield
finally:
setattr(module, 'print', print)
def line_generator():
fd = io.StringIO()
with grab_stdout(mod1, fd):
mod1.bogus_function()
fd.seek(0)
for line in fd:
yield line.rstrip('\r\n') + '<br>'
for t in enumerate(line_generator()):
print('line %d: %r' % t)
grab_stdout()
上下文管理器将module
的打印调用重定向到类文件对象fd
。在函数line_generator()
中,grab_stdout()
用于在bogus_function
对象StringIO
中存储fd
的打印输出。其余的应该是不言自明的。
如果您不确切知道是否在相关函数的调用树中的其他模块中调用了print,则可以按如下方式修改grab_stdout
:
import builtins
print_orig = builtins.print
@contextlib.contextmanager
def grab_stdout_global(fd):
def monkey_print(*args, **kwargs):
kwargs['file'] = fd
print_orig(*args, **kwargs)
builtins.print = monkey_print
try:
yield
finally:
builtins.print = print_orig