Python 禁用除在被调用函数中完成的打印之外的所有打印
我有一个函数,在该函数中,我从同一个模块或其他模块调用一些函数:Python 禁用除在被调用函数中完成的打印之外的所有打印,python,printing,decorator,Python,Printing,Decorator,我有一个函数,在该函数中,我从同一个模块或其他模块调用一些函数: from __future__ import print_function def func(): print("Inside func") def my_func(): print("Starting inside my_func ") func() print("In my_func") func() 执行my_func将输出以下内容: Starting inside my_fun
from __future__ import print_function
def func():
print("Inside func")
def my_func():
print("Starting inside my_func ")
func()
print("In my_func")
func()
执行my_func
将输出以下内容:
Starting inside my_func
Inside func
In my_func
Inside func
但我只想看看
Starting inside my_func
In my_func
所以,我想禁用所有打印,除了制作的打印
直接在函数my_func()
中。这可能包括对函数的递归调用。因此,使用堆栈级别执行某些操作将不起作用
我可以考虑这样做
def func():
print("Inside func")
def my_print(*args):
print(*args)
def my_func():
global my_print, print
my_print("Starting inside my_func ")
print = functools.partial(print, file=open(os.devnull, 'w'))
func()
print = functools.partial(print, file=sys.stdout)
my_print("In my_func")
print = functools.partial(print, file=open(os.devnull, 'w'))
func()
print = functools.partial(print, file=sys.stdout)
但这涉及到修改函数代码,而且似乎有点不成熟。理想情况下,我希望使用decorator实现这一点,而不需要修改函数代码
最自然的方法是找到未在
my_func
中调用的打印,并将它们输出到包装器中的os.devnull
。但我不知道怎么做。提前感谢。您可以将对print
函数的引用保存在变量orig\u print
中,并使用不执行任何操作的函数覆盖print
,然后在要允许打印的函数上使用修饰符,使用ast.NodeTransformer
子类将对print
的所有调用重命名为orig\u print
:
from __future__ import print_function
import inspect
import ast
from textwrap import dedent
orig_print = print
print = lambda *args, **kwargs: None
class EnablePrint(ast.NodeTransformer):
# remove the enable_print decorator from the decorator list so the transformed
# function won't be re-decorated when executed
def visit_FunctionDef(self, node):
node.decorator_list = [
decorator for decorator in node.decorator_list
if not isinstance(decorator, ast.Name) or decorator.id != 'enable_print'
]
self.generic_visit(node)
return node
def visit_Call(self, node):
if node.func.id == 'print':
node.func.id = 'orig_print'
return node
def enable_print(func):
node = ast.parse(dedent(inspect.getsource(func)))
EnablePrint().visit(node)
scope = {}
exec(compile(node, inspect.getfile(func), 'exec'), func.__globals__, scope)
return scope[func.__name__]
以便:
def func():
print("Inside func")
@enable_print
def my_func():
print("Starting inside my_func ")
func()
print("In my_func")
func()
my_func()
def func():
print("Inside func")
@disable_prints
def my_func():
pprint("Starting inside my_func")
func()
pprint("In my_func")
func()
my_func()
将输出:
Starting inside my_func
In my_func
@布莱辛给出了一个很好的方法。但我最终在函数中使用
pprint.pprint
解决了问题,并禁用了print
的输出。这是因为pprint
使用了更低级的流。write(“…”)
而不是打印上的引导。守则:
def disable_prints(f):
@functools.wraps(f)
def decorated(*args, **kwargs):
global print
# Disable all calls made to print(...) by relacing stdout with devnull
print = functools.partial(print, file=open(os.devnull, 'w'))
f_returns = f(*args, **kwargs)
# Restore back
print = functools.partial(print, file=sys.stdout)
return f_returns
return decorated
以便:
def func():
print("Inside func")
@enable_print
def my_func():
print("Starting inside my_func ")
func()
print("In my_func")
func()
my_func()
def func():
print("Inside func")
@disable_prints
def my_func():
pprint("Starting inside my_func")
func()
pprint("In my_func")
func()
my_func()
将输出:
Starting inside my_func
In my_func
我的回答能解决你的问题吗?如果是,你能接受这个答案吗?如果没有,请让我知道这个答案没有解决哪些问题。嗨,谢谢。它起作用了。如果有更多的人回答,我会等的。没问题。如果您觉得新答案更好,您随时可以接受。此答案实际上没有回答问题,因为它实际上没有在装饰功能中使用print
,其中print
仍处于禁用状态,这不符合您的目标“我想禁用除函数my_func()
“。此外,在函数调用期间全局重写print
不是线程安全的,因此,如果调用修饰函数的线程需要同时运行,则当其他线程不在此函数内时,当此函数内的线程需要print
禁用时,将由其他线程重新启用打印。此外,pprint
的行为与print
截然不同。与print
不同,pprint
始终打印给定对象的\uuu repr\uuuu
方法的输出,因此pprint('hi')
将输出'hi'
,而不是hi
,因此不是print
生成用户友好输出的好替代品。要点如下。谢谢离开ans,这似乎更容易理解。