python - 禁用所有打印,除了在调用函数中完成的打印
问题描述
我有一个函数,我从同一个模块或其他一些模块中调用一些函数:
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)
但这涉及修改功能代码,似乎有点hacky。理想情况下,我希望使用装饰器来执行此操作,而无需修改功能代码。
最自然的方法是找到未调用的打印my_func
并将它们输出到os.devnull
包装器中。但我找不到如何做到这一点。提前致谢。
解决方案
您可以将对该print
函数的引用保存在一个变量中orig_print
并用一个什么都不做的函数覆盖print
,然后在您希望允许打印的函数上使用一个装饰器,print
以orig_print
使用ast.NodeTransformer
子类重命名所有调用:
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()
会输出:
Starting inside my_func
In my_func
推荐阅读
- java - Heroku Spring Boot start
- python - Python 单元测试相关函数
- javascript - Firebase:未定义 Firestore 事务?
- ember.js - 为“模型”钩子设置别名
- angular - 角度 routerLink 属性单击不适用于 nwjs
- python - openpyxl:TypeError:load_workbook()得到了一个意外的关键字参数“guess_types”
- python - Django - Signal.disconnect 不断开信号
- php - 将 1 天添加到一周中的每一天(星期一,星期二..)
- java - 客户端 REST 抛出 javax.ws.rs.NotFoundException
- java - java中的正则表达式处理程序