python捕获其他模块生成的sys.stdout和sys.exit

python捕获其他模块生成的sys.stdout和sys.exit,python,output,capture,sys,Python,Output,Capture,Sys,我有两个脚本如下,但我不能修改foo.py 我已经在bar.py中编写了代码来捕获foo.py生成的输出,以便在输出到终端之前修改输出 但是,捕获不起作用。我做错了什么 foo.py ---- import sys def some_func(): sys.stdout.write("hello") sys.stdout.flush() def foo(): some_func() sys.exit(1) 这是我可以修改的模块: ba

我有两个脚本如下,但我不能修改foo.py 我已经在bar.py中编写了代码来捕获foo.py生成的输出,以便在输出到终端之前修改输出

但是,捕获不起作用。我做错了什么

foo.py
----
import sys


def some_func():
    sys.stdout.write("hello")
    sys.stdout.flush()


def foo():
    some_func()
    sys.exit(1)
这是我可以修改的模块:

bar.py
----

import io
from contextlib import redirect_stdout
from foo import foo



f = io.StringIO()
with redirect_stdout(f):
    foo()
s = f.getvalue()
print(s)
编辑:

最终解决方案

import io
from contextlib import redirect_stdout
from foo import foo


def capture_output(func):
    f = io.StringIO()
    try:
        with redirect_stdout(f):
            func()
    except SystemExit:
        return f.getvalue()


capture_output(foo)

问题是调用in
foo.py

bar.py
中调用
foo()
,然后到达
foo()
函数的最后一行时,解释器立即退出,调用
foo()
后的
bar.py
的其余部分不会执行。因此,您正在正确地捕获标准输出——它只是在程序退出之前没有打印出来

如果您无法更改的文件实际上包含对
sys.exit(1)
的直接调用,并且您希望在不退出的情况下处理该调用,则可以将对
foo()
的调用包装在
try
/
块中,但
块除外。但是,根据实际调用的
sys.exit(1)
的上下文,使用类似于

编辑: 回复:您的评论如下

  • 如果输出可能指向
    sys.stdout
    sys.stderr
    ,则应说明其中一个。例如,你可以做:

    从contextlib导入重定向\u stdout,重定向\u stderr
    tmp_stdout,tmp_stderr=StringIO(),StringIO()
    使用redirect_stdout(tmp_stdout),redirect_stderr(tmp_stderr):
    foo()
    tmp_stdout,tmp_stderr=tmp_stdout.getvalue(),tmp_stderr.getvalue()
    
  • 是--
    sys.exit()

    试试看:
    #你的代码在这里
    除系统退出外:
    通过
    
    虽然我觉得这有点粗略。通常,非零退出代码表示程序中某个地方出现了错误,因此在绝大多数情况下,故意引发的
    sys.exit(1)
    可能不是您想要默默抑制的


  • 这是您可以尝试的:

    import sys
    import os
    import importlib
    
    # foo.py
    
    def some_func():
        sys.stdout.write("hello")
        sys.stdout.flush()
    
    
    def foo():
        some_func()
        sys.exit(1)
    
    
    # bar.py
    
    original = sys.stdout
    
    def start_capture():
        sys.stdout = open('tmpfile', 'w')
    
    def stop_capture():
        sys.stdout.close()
        sys.stdout = original
        data = ""
        with open('tmpfile', 'r') as f:
            data = f.read()
        os.remove('tmpfile')
        return data
    
    
    start_capture()
    try:
        foo()
    except SystemExit:
        print('\nFoo Exit!\n')
    print(stop_capture())
    

    出于演示目的,我将foo.py放在同一个文件中,但主要部分是重定向stdout

    我无法修改foo,这就是我试图捕获的内容。是否有方法捕获在其他模块中调用的sys.exit,实际上不是exit,而是处理它?@darkman请检查我的答案once@darkman谢谢你的澄清,我已经更新了我的答案谢谢你的代码,因为它可以完成工作,所以我感谢你的贡献,但实际上@paxton4416更适合我的需要。