Подавить вывод из функции - PullRequest
1 голос
/ 17 февраля 2020

есть вещь, которую я хочу исключить, это когда функция print для вывода, я знаю о переопределении sys.stdout.write, которое использует функция print(). но я думаю, что это не идеальное решение для этого. Я ищу идеальный способ Pythoni c для этого?

from timeit import Timer
from functools import partial

def timing_decorator(function):
    def wrapper(*args, **kwargs):
        # print(function)
        callable_f = partial(function, *args, **kwargs)
        # print(dir(Timer))
        total = Timer(callable_f).timeit(1)
        print(total)
        return total
    return wrapper

# example function
@timing_decorator
def hello(arg):
    print(arg)
    return

hello('hi')

Это выводит:

hi
0.00036

Мой ожидаемый вывод будет:

0.00036

Ответы [ 2 ]

1 голос
/ 17 февраля 2020

Мы можем использовать patch из модуля unittest стандартной библиотеки, чтобы переопределить функциональность print только при вызове функции, которая использует эту оболочку с помощью менеджера контекста. Тем не менее, с учетом вышесказанного, подход, который использует @kindall, предпочтительнее, так как он более Pythoni c, учитывая, что в этом ответе используется что-то изначально предназначенное для целей тестирования.

from unittest.mock import patch

def timing_decorator(function):
    def wrapper(*args, **kwargs):
        # print(function)
        callable_f = partial(function, *args, **kwargs)
        with patch('__main__.print'):
            total = Timer(callable_f).timeit(1)
        print(f"{function.__name__}: {total:.5f}ms")
        return total
    return wrapper
0 голосов
/ 17 февраля 2020

Вы можете создать файлоподобный объект, у которого есть метод write(), который ничего не делает, и заставить ваш декоратор заменить его на sys.stdout (и восстановить исходный стандартный вывод после вызова функции).

import sys

class NoOutput:
    def write(text):
        pass

no_output = NoOutput()

def timing_decorator(function):
    def wrapper(*args, **kwargs):
        callable_f = partial(function, *args, **kwargs)
        old_stdout, sys.stdout = sys.stdout, no_output
        try:
            total = Timer(callable_f).timeit(1)
        finally:
            sys.stdout = old_stdout
        print(f"{function.__name__}: {total:.5f}ms")
        return total
    return wrapper

Обратите внимание на использование try / finally, чтобы убедиться, что стандартный вывод восстанавливается, даже если в функции возбуждено исключение.

...