鉴于
有许多函数可以执行一些计算。在某些情况下(为了调试或监控过程),定期打印计算结果是很方便的。像这样:
def some_calculations(b, a):
print('Начали вычислять...')
# чего-то вычисляем
s = b + a
print(f'Закончили вычислять. Результаты: {s}')
print('Опять начали вычислять...')
# чего-то вычисляем
p = b * a
print(f'Закончили вычислять. Результаты: {p}')
# и тут таких или подобных итераций несколько
return s, p
但在某些情况下,为了不浪费时间在长时间的输出操作上,我需要禁用所有这些打印。首先,我想定义某种可以传递给这些函数的布尔变量,并在每次打印附近描述根据这个布尔变量是否输出/不输出的条件。但后来我想一定有办法可以关闭所有的打印。我没有依靠自己的知识,而是去寻找并找到了它。
# выключили
sys.stdout = open(os.devnull, 'w')
# включили
sys.stdout = sys.__stdout__
接下来,我决定测量执行时间
- 只是功能
- 输出关闭
- 打印被包装在取决于布尔标志变量的条件中的函数。
以下是带有标志的版本:
def some_calculations(b, a, flag = False):
if flag:
print('Начали вычислять...')
# чего-то вычисляем
s = b + a
if flag:
print(f'Закончили вычислять. Результаты: {s}')
if flag:
print('Опять начали вычислять...')
# чего-то вычисляем
p = b * a
if flag:
print(f'Закончили вычислять. Результаты: {p}')
# и тут таких или подобных итераций несколько
return s, p
测量结果表明,关闭输出的选项可使打印函数的执行时间缩短5 倍,而带有标志的选项可使执行时间缩短 65 倍。造成这种差异的原因很明显——开头指出的方法不会禁用打印,它仍然执行功能print,仅输出到devnull,也就是说,它只是抑制输出到控制台。并且标志绕过打印功能。
问题
是否有可能禁用某个函数(例如打印),而无需将每个函数调用包装在条件中,从而使禁用实际上绕过该函数,从而提供运行时好处,而不是简单地抑制输出?
这是 Python,您可以在这里重新定义几乎任何东西。那些。您甚至可以覆盖该函数,
print使其不执行任何操作:但总的来说,最好学习日志记录,它正是为这样的使用场景而发明的——有时你需要输出信息,有时则不需要。有时,需要不同程度的细节。
附言关于正确记录:
使用此日志记录选项,如文档中所写:
也就是说,例如,如果您设置日志记录级别,使得记录器调用不应将任何内容写入日志,则参数将不会被替换到模板中。尽管这仍然比非日志版本慢,但它不需要进行棘手的代码修改就可以获得带日志和不带日志的选项。在记录器配置中指定所需的日志记录级别就足够了。
我将扩展评论中的想法:编写一个禁用标准输出的类。通过构造调用函数
with和挑战
嗯,这是控制台的结果。
最好使用专为此类操作设计的包。
logging例子:
DEBUG):INFO):此代码对我4.1c有效:
如果您“关闭”日志记录(
LOG = False),则2.2 秒:如果你完全注释掉调用
log(# log(f'calc_sum({a}, {b}) == {c}'),那么0.6s:我们将差值4.1 - 0.6 = 3.5作为100%。然后“禁用”日志(4.1 - 2.2 = 1.9)返回54%。如果我们完全取消挑战,我们将再获得46% 。
因为挑战
log(f'calc_sum({a}, {b}) == {c}')是分两个阶段计算的。第一步是计算
f'...'。虽然它被称为字符串,但它并不是文字,而是一个成熟的函数调用。通过“禁用”日志记录,我们并没有删除其计算,但它仍然浪费时间。第二阶段是印刷本身。 “禁用”可以阻止它,这里一切都很好。
结果,我们的“开关”只起到了一半的作用。如果我们想保留格式字符串的语法,这几乎是不可避免的。我们希望它能够方便。因此我们需要一个选项
if LOG: print(...):3.8c启用日志。
略高于0.6c,且对数为“关闭”(
LOG = False):略低于0.6c ,带有注释代码。
在此选项中,“禁用”可节省98%的时间。尽管并不美观,但这已经是一个可行的选择。因此,使用
if与选项一样快的折衷方案if:只需创建自己的带有条件的打印函数即可。例如:
该标志
is_p既可以位于函数本身中,也可以位于类中(与函数一起)。通过改变标志,您可以改变行为。更新。类似的方法,但不使用全局变量
一般来说,更正确的解决方案可能是创建自己的记录器类,根据其设置可以更方便地配置打印/输出到文件(例如,添加调用时间)
这是Dmitry和CrazyElf的答案的组合:
使用方式如下:
实例:https://www.online-python.com/G17kaOdlZw