如何在Python中获取所有先前的打印。

huangapple go评论83阅读模式
英文:

How to get all previous print in Python

问题

I'm currently using some functions to store all print in Python. And it gets all print AFTER the function has finished. Here is a sample snippet:

import io
import sys
import time
import traceback

def return_std(func):
    def wrapper(*args, **kwargs):
        old_stdout = sys.stdout
        sys.stdout = buffer = io.StringIO()
        try:
            func(*args, **kwargs)
        except:
            print(traceback.format_exc())
        finally:
            sys.stdout = old_stdout
            body = buffer.getvalue()
            buffer.close()
            sys.stdout = old_stdout  # Move this line here to see output instantly
        return body
    return wrapper

@return_std
def some_useful_function():
    print('so this line is executed at ' + time.strftime('%X'))
    time.sleep(5)

print('program execute at ' + time.strftime('%X'))
std_of_some_useful_function = some_useful_function()
print(std_of_some_useful_function)
print('but we cannot know if it succeeded or failed before ' + time.strftime('%X'))

Output:

program execute at 11:11:11
so this line is executed at 11:11:11
but we cannot know if it succeeded or failed before 11:11:16

I moved sys.stdout = old_stdout inside the finally block to see the output instantly and store all previous print at 11:11:16.

英文:

I'm currently using some functions to store all print in Python

And it get all print AFTER the function has finished

Here is a sample snippet

import io
import sys
import time
import traceback

def return_std(func):
    def wrapper(*args, **kwargs):
        old_stdout = sys.stdout
        sys.stdout = buffer = io.StringIO()
        try:
            func(*args, **kwargs)
        except:
            print(traceback.format_exc())
        finally:
            sys.stdout = old_stdout
            body = buffer.getvalue()
            buffer.close()
        return body
    return wrapper

@return_std
def some_useful_function():
    print('so this line is executed at ' + time.strftime('%X'))
    time.sleep(5)

print('program execute at ' + time.strftime('%X'))
std_of_some_useful_function = some_useful_function()
print(std_of_some_useful_function)
print('but we can not know if it succeeded or failed before ' + time.strftime('%X'))

output

program execute at 11:11:11
so this line is executed at 11:11:11

but we can not know if it succeeded or failed before 11:11:16

This way captures all print and error in some_useful_function, and stores it as the function return. But print will not show BEFORE this function has finished

How should I modify the wrapper return_std, so I can see the output at 11:11:11 instantly (like it was really printed), and get all previous print stored at 11:11:16

答案1

得分: 2

class SavedStdOut(io.StringIO):

    def __init__(self, stdout):
        super().__init__()
        self.stdout = stdout

    def write(self, s: str):
        self.stdout.write(s)
        return super().write(s)

foo = SavedStdOut(sys.stdout)
foo.write('Hello\n')  # Hello
print('Buffer:', foo.getvalue())  # Buffer: Hello

import io
import sys
import time
import traceback

class SavedStdOut(io.StringIO):

    def __init__(self, stdout):
        super().__init__()
        self.stdout = stdout

    def write(self, s: str):
        self.stdout.write(s)
        return super().write(s)

def return_std(func):
    def wrapper(*args, **kwargs):
        sys.stdout = buffer = SavedStdOut(sys.stdout)
        try:
            func(*args, **kwargs)
        except:
            print(traceback.format_exc())
        finally:
            sys.stdout = buffer.stdout
            body = buffer.getvalue()
            buffer.close()
        return body
    return wrapper

@return_std
def some_useful_function():
    print('so this line is executed at ' + time.strftime('%X'))
    time.sleep(5)

print('program execute at ' + time.strftime('%X'))
std_of_some_useful_function = some_useful_function()
print('saved stdout:', std_of_some_useful_function)
print('but we can not know if it succeeded or failed before ' + time.strftime('%X'))

Output:

program execute at 03:52:01
so this line is executed at 03:52:01  # Printed as soon as print() is called
saved stdout: so this line is executed at 03:52:01

but we can not know if it succeeded or failed before 03:52:06
英文:

You can create a subclass of io.StringIO and override the write() method so that it writes to a saved version of sys.stdout aswell as writing to it's internal buffer

class SavedStdOut(io.StringIO):

    def __init__(self, stdout):
        super().__init__()
        self.stdout = stdout

    def write(self, s: str):
        self.stdout.write(s)
        return super().write(s)

The class then writes to the passed file and saves the written data

foo = SavedStdOut(sys.stdout)
foo.write('Hello\n')  # Hello
print('Buffer:', foo.getvalue())  # Buffer: Hello

A complete example

import io
import sys
import time
import traceback


class SavedStdOut(io.StringIO):

    def __init__(self, stdout):
        super().__init__()
        self.stdout = stdout

    def write(self, s: str):
        self.stdout.write(s)
        return super().write(s)


def return_std(func):
    def wrapper(*args, **kwargs):
        sys.stdout = buffer = SavedStdOut(sys.stdout)
        try:
            func(*args, **kwargs)
        except:
            print(traceback.format_exc())
        finally:
            sys.stdout = buffer.stdout
            body = buffer.getvalue()
            buffer.close()
        return body
    return wrapper


@return_std
def some_useful_function():
    print('so this line is executed at ' + time.strftime('%X'))
    time.sleep(5)


print('program execute at ' + time.strftime('%X'))
std_of_some_useful_function = some_useful_function()
print('saved stdout:', std_of_some_useful_function)
print('but we can not know if it succeeded or failed before ' + time.strftime('%X'))

Output:

program execute at 03:52:01
so this line is executed at 03:52:01  # Printed as soon as print() is called
saved stdout: so this line is executed at 03:52:01

but we can not know if it succeeded or failed before 03:52:06

答案2

得分: 1

Create a my_print class with __call__ operator and overwrite the builtins.print method with your class like this.

class MyPrint():

    def __init__(self):
        self.__buffer = io.StringIO()
        self.__old_print = __builtin__.print

    def getvalue(self):
        return self.__buffer.getvalue()

    def close(self):
        self.__buffer.close()
        __builtin__.print = self.__old_print

    def __call__(self, *args, **kwargs):
        self.__buffer.write(args[0])
        self.__old_print(*args, **kwargs)

Use the return_std decorator to capture the standard output of a function like this:

def return_std(func):
    def wrapper(*args, **kwargs):
        my_print = MyPrint()
        __builtin__.print = my_print
        try:
            func(*args, **kwargs)
        except:
            print(traceback.format_exc())
        finally:
            body = my_print.getvalue()
            my_print.close()
        return body
    return wrapper

@return_std
def some_useful_function():
    print('so this line is executed at ' + time.strftime('%X'))
    time.sleep(1)

print('program execute at ' + time.strftime('%X'))
std_of_some_useful_function = some_useful_function()
print(std_of_some_useful_function)
print('but we can not know if it succeeded or failed before ' + time.strftime('%X'))

This code allows you to capture and analyze the standard output of a function.

英文:

Not convinced that whatever you are trying to do is a good idea but you can do it like so.

Create a my_print class with __call__ operator and overwrite the builtins.print method with your class like this.

class MyPrint():

    def __init__(self):
        self.__buffer = io.StringIO()
        self.__old_print = __builtin__.print

    def getvalue(self):
        return self.__buffer.getvalue()

    def close(self):
        self.__buffer.close()
        __builtin__.print = self.__old_print

    def __call__(self, *args, **kwargs):
        self.__buffer.write(args[0])
        self.__old_print(*args, **kwargs)

def return_std(func):
    def wrapper(*args, **kwargs):
        my_print = MyPrint()
        __builtin__.print = my_print
        try:
            func(*args, **kwargs)
        except:
            print(traceback.format_exc())
        finally:
            body = my_print.getvalue()
            my_print.close()
        return body
    return wrapper

@return_std
def some_useful_function():
    print('so this line is executed at ' + time.strftime('%X'))
    time.sleep(1)

print('program execute at ' + time.strftime('%X'))
std_of_some_useful_function = some_useful_function()
print(std_of_some_useful_function)
print('but we can not know if it succeeded or failed before ' + time.strftime('%X'))

huangapple
  • 本文由 发表于 2023年3月23日 11:21:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75818990.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定