登录框架

2024-01-09

想象一下有一个框架提供了一个名为logutils.set_up()它根据某些配置设置日志记录。

应尽早设置日志记录,因为导入库期间发出的警告不应丢失。

由于旧方法(if __name__=='__main__':)看起来很难看,我们使用控制台脚本入口点来注册main() method.

# foo/daily_report.py
from framework import logutils
logutils.set_up()
def main():
    ...

我的问题是logutils.set_up()可能会被调用两次:

想象一下有第二个控制台脚本调用logutils.set_up() and imports daily_report.py.

我可以更改框架代码set_up()在第二次调用中不执行任何操作logutils.set_up(),但这感觉很笨拙。我想避免它。

我怎样才能确定logutils.set_up()只执行一次?


有几种方法可以实现该目标,每种方法都有其优点和缺点。

(其中一些与其他答案重叠。我无意抄袭,只是为了提供全面的答案)。


方法一:函数应该做到这一点

保证函数只执行一次的一种方法是使函数本身有状态,使其“记住”它已经被调用过。这或多或少是@eestrada 和@qarma 所描述的。

至于实现这一点,我同意 @qarma 的观点,即使用记忆化是最简单、最理想的方法。互联网上有一些简单的 python 记忆装饰器。标准库中包含的一个是functools.lru_cache。您可以简单地使用它,例如:

@functools.lru_cache
def set_up():  # this is your original set_up() function, now decorated
    <...same as before...>

这里的缺点是它可以说不是set_up维持国家的责任,只是一种职能。有人可以争论这一点should如果被调用两次,则执行两次,并且调用者有责任仅在需要时调用它(如果您确实想运行它两次怎么办)?一般的论点是,函数(为了有用和可重用)不应该对其调用的上下文做出假设。

这个论点在你的情况下有效吗?由您决定。

这里的另一个缺点是,这可以被视为滥用记忆工具。 Memoization是与函数式编程密切相关的工具,应该应用于纯函数。记住一个函数意味着“不需要再次运行它,因为我们已经知道了result”,而不是“不需要再次运行它,因为有一些副作用我们想避免”。

方法二:你认为丑的那个(if __name__=='__main__')

您在问题中已经提到的最常见的Python方式是使用臭名昭著的if __name__=='__main__' https://stackoverflow.com/q/419163/2096752构造。

这保证了该函数仅被调用一次,因为它仅从名为的模块中调用__main__,并且解释器保证您的进程中只有一个这样的模块。

这有效。没有任何并发​​症或警告。这是在 python 中运行主代码(包括设置代码)的方式。已经被考虑了pythonic只是因为它在 python 中非常常见(因为没有更好的方法)。

唯一的缺点是它可以说是丑陋的(从美观角度来看,而不是从代码质量角度来看)。我承认,在我最初几次看到或写下它时,我也皱起了眉头,但你会越来越喜欢它。

方法 3:利用 python 的模块导入机制

Python 已经有一个缓存机制来防止模块被双重导入。您可以通过在新模块中运行设置代码然后导入它来利用此机制。这与@rll 的答案类似。这很简单,要做到:

# logging_setup.py
from framework import logutils
logutils.set_up()

现在,每个调用者都可以通过导入新模块来运行它:

# foo/daily_report.py
import logging_setup # side effect!
def main():
    ...

由于模块仅导入一次,set_up只被调用一次。

这里的缺点是它违反了“显式优于隐式”的原则。 IE。如果你想调用一个函数,就调用它。运行对模块导入时间有副作用的代码并不是一个好习惯。

方法 4:猴子修补

这是迄今为止该答案中最糟糕的方法。不要使用它。但这仍然是完成工作的一种方法。

这个想法是,如果您不希望该函数在第一次调用后被调用,请在第一次调用后对其进行猴子修补(阅读:破坏它)。

from framework import logutils
logutils.set_up_only_once()

Where set_up_only_once可以这样实现:

def set_up_only_once():
    # run the actual setup (or nothing if already vandalized):
    set_up()
    # vandalize it so it never walks again:
    import sys
    sys.modules['logutils'].set_up = lambda: None

缺点:你的同事会讨厌你。


tl;dr:

最简单的方法是使用记忆functools.lru_cache,但它可能不是代码质量方面的最佳解决方案。该解决方案是否足够适合您的情况取决于您。

最安全、最Pythonic的方法,虽然不赏心悦目,但使用if __name__=='__main__': ....

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

登录框架 的相关文章

  • 使用 pythonbrew 编译 Python 3.2 和 2.7 时出现问题

    我正在尝试使用构建多个版本的 python蟒蛇酿造 http pypi python org pypi pythonbrew 0 7 3 但我遇到了一些测试失败 这是在运行的虚拟机上 Ubuntu 8 04 32 位 当我使用时会发生这种情
  • 没有名为 crypto.cipher 的模块

    我现在正在尝试加密一段时间 我最近得到了这个基于 python 的密码器 名为PythonCrypter https github com jbertman PythonCrypter 我对 Python 相当陌生 当我尝试通过终端打开 C
  • Python 中的 Lanczos 插值与 2D 图像

    我尝试重新缩放 2D 图像 灰度 图像大小为 256x256 所需输出为 224x224 像素值范围从 0 到 1300 我尝试了两种使用 Lanczos 插值来重新调整它们的方法 首先使用PIL图像 import numpy as np
  • Python 的键盘中断不会中止 Rust 函数 (PyO3)

    我有一个使用 PyO3 用 Rust 编写的 Python 库 它涉及一些昂贵的计算 单个函数调用最多需要 10 分钟 从 Python 调用时如何中止执行 Ctrl C 好像只有执行结束后才会处理 所以本质上没什么用 最小可重现示例 Ca
  • 将 Matplotlib 误差线放置在不位于条形中心的位置

    我正在 Matplotlib 中生成带有错误栏的堆积条形图 不幸的是 某些层相对较小且数据多样 因此多个层的错误条可能重叠 从而使它们难以或无法读取 Example 有没有办法设置每个误差条的位置 即沿 x 轴移动它 以便重叠的线显示在彼此
  • Python(Selenium):如何通过登录重定向/组织登录登录网站

    我不是专业程序员 所以请原谅任何愚蠢的错误 我正在做一些研究 我正在尝试使用 Selenium 登录数据库来搜索大约 1000 个术语 我有两个问题 1 重定向到组织登录页面后如何使用 Selenium 登录 2 如何检索数据库 在我解决
  • 通过最小元素比较对 5 个元素进行排序

    我必须在 python 中使用元素之间的最小比较次数来建模对 5 个元素的列表进行排序的执行计划 除此之外 复杂性是无关紧要的 结果是一个对的列表 表示在另一时间对列表进行排序所需的比较 我知道有一种算法可以通过 7 次比较 总是在元素之间
  • 从字符串中删除识别的日期

    作为输入 我有几个包含不同格式日期的字符串 例如 彼得在16 45 我的生日是1990年7月8日 On 7 月 11 日星期六我会回家 I use dateutil parser parse识别字符串中的日期 在下一步中 我想从字符串中删除
  • 如何在 Python 中检索 for 循环中的剩余项目?

    我有一个简单的 for 循环迭代项目列表 在某些时候 我知道它会破裂 我该如何退回剩余的物品 for i in a b c d e f g try some func i except return remaining items if s
  • 以编程方式停止Python脚本的执行? [复制]

    这个问题在这里已经有答案了 是否可以使用命令在任意行停止执行 python 脚本 Like some code quit quit at this point some more code that s not executed sys e
  • OpenCV 无法从 MacBook Pro iSight 捕获

    几天后 我无法再从 opencv 应用程序内部打开我的 iSight 相机 cap cv2 VideoCapture 0 返回 并且cap isOpened 回报true 然而 cap grab 刚刚返回false 有任何想法吗 示例代码
  • 从 Flask 访问 Heroku 变量

    我已经使用以下命令在 Heroku 配置中设置了数据库变量 heroku config add server xxx xxx xxx xxx heroku config add user userName heroku config add
  • 如何使用Python创建历史时间线

    So I ve seen a few answers on here that helped a bit but my dataset is larger than the ones that have been answered prev
  • Pygame:有没有简单的方法可以找到按下的任何字母数字的字母/数字?

    我目前正在开发的游戏需要让人们以自己的名义在高分板上计时 我对如何处理按键有点熟悉 但我只处理过寻找特定的按键 有没有一种简单的方法可以按下任意键的字母 而不必执行以下操作 for event in pygame event get if
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • Jupyter Notebook 内核一直很忙

    我已经安装了 anaconda 并且 python 在 Spyder IPython 等中工作正常 但是我无法运行 python 笔记本 内核被创建 它也连接 但它始终显示黑圈忙碌符号 防火墙或防病毒软件没有问题 我尝试过禁用两者 我也无法
  • Rocket UniData/UniVerse:ODBC 无法分配足够的内存

    每当我尝试使用pyodbc连接到 Rocket UniData UniVerse 数据时我不断遇到错误 pyodbc Error 00000 00000 Rocket U2 U2ODBC 0302810 Unable to allocate
  • 从列表指向字典变量

    假设你有一个清单 a 3 4 1 我想用这些信息来指向字典 b 3 4 1 现在 我需要的是一个常规 看到该值后 在 b 的位置内读写一个值 我不喜欢复制变量 我想直接改变变量b的内容 假设b是一个嵌套字典 你可以这样做 reduce di
  • 如何使用 Pycharm 安装 tkinter? [复制]

    这个问题在这里已经有答案了 I used sudo apt get install python3 6 tk而且效果很好 如果我在终端中打开 python Tkinter 就可以工作 但我无法将其安装在我的 Pycharm 项目上 pip
  • 如何将输入读取为数字?

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 Why are x and y下面的代码中使用字符串而不是整数 注意 在Python 2

随机推荐

  • 如何从文档中删除所有肖像图片

    我正在对文档图像进行 OCR 处理 我想检测所有图片并从文档图像中删除 我想保留文档图像中的表格 一旦我检测到图片 我就会将其删除 然后进行 OCR 我试图找到轮廓试图检测所有更大的区域 不幸的是它也检测到表格 还如何删除在文档图像中保留其
  • 通过 Python 代码使用 SignalR 服务器

    将 Python 与 SignalR 集成有哪些选项 Python 代码是大型第三方产品的一部分 与语言偏好无关 SignalR 服务器提供对现有 NET 产品的订阅 我们希望通过 Python 重用 NET SignalR 服务器 pyt
  • Java中如何随机选择图片?

    我正在制作一个将使用以下代码的程序 JLabel MyImage new JLabel new ImageIcon image1 png 但是 我想让随机图片出现 比如 image2 image3 image4 我该如何做到这一点 不使用L
  • @RequestMapping 在 Spring Boot 内部如何工作?

    RestController RequestMapping employee public class Employee RequestMapping save public void saveEmployee saving employe
  • blockIdx 与区块执行顺序相关吗?

    之间有什么关系吗blockIdx以及线程块在 GPU 设备上执行的顺序 我的动机是 我有一个内核 其中多个块将从全局内存中的同一位置读取 如果这些块能够同时运行 那就太好了 因为 L2 缓存命中很好 在决定如何将这些块组织成网格时 可以肯定
  • 如何识别无法嵌入文件的 YouTube 视频

    我有一个移动应用程序 可以在网络视图中嵌入一些 YouTube 视频 问题是 使用 YouTube Data API v3 我得到了 可嵌入 要显示的项目 但其中一些说 视频不可用 当我将相同的代码粘贴到 jsfiddle 或域或某种网络服
  • docker jboss7 战争提交。服务器启动失败且无法恢复

    有没有办法将 war 文件部署到在 docker 容器内运行的 Jboss as7 中 因为我的 jboss 服务器在 docker 提交后似乎失败了 Could not rename usr local share jboss stand
  • Keycloak + Kerberos 身份验证:机制级别:无效参数 (400) - 无法找到适当类型的密钥来解密 AP REP - 使用 HMAC 的 RC4

    我有以下内容 JBoss EAP 7 2 2 上的 Spring Web 应用程序 Machine CentOs CentO 上的 Keycloak 3 3 4 活动目录 我们在 OpenJDK 8 上运行 用户使用其 Active Dir
  • CG 3.0会泄露吗?

    我发现 CG 似乎存在内存泄漏 我通过 nvidia com 提交了一份报告 但如果您尝试这样做here http will sherif appspot com html d3d11 DirectWrite html 如果你删除那行 cg
  • 语法错误:编译 ejs 时参数列表后缺少 )

    编译 ejs 时 我收到错误 参数列表后缺少 我尝试了很多次 但找不到问题所在 这是导致错误的 ejs 这段代码有什么问题 h2 class page title Products h2 br a href admin products a
  • WPF Ribbon - 隐藏快速访问工具栏

    如何在 WPF 功能区中隐藏快速访问工具栏 For 您可以使用隐藏它VisualTreeHelper 上Loaded事件处理程序 只需将包含快速访问工具栏的行大小调整为 0 private void RibbonLoaded object
  • 安卓L | libusb_init 返回 LIBUSB_ERROR_OTHER (-99)

    我尝试使用libusb在未 root 的 Nexus 5 上 如建议的那样这种方法 https stackoverflow com a 24243605 902217 通过将 USB 文件描述符从 java 传输到本机端 我的应用程序通过以
  • 将空图添加到ggplot2中的facet_wrap

    我正在尝试创建 3 个图 其中所有面板应具有相同的大小 所以我认为解决方案可能是facet wrap 我的问题是 我不希望每个图表中有相同数量的图表 df lt data frame group c 1 1 2 2 2 3 3 name c
  • 在树枝模板中设置多维数组中单个对象的值

    对于项目需要 我需要在渲染之前更改一些表单字段数据 为此 我迭代表单元素并动态更改我需要的值 问题是我无法改变价值 我收到这个错误 Unexpected token punctuation of value end of statement
  • Emacs 搜索和替换的好教程 + 参考吗? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 对于 Emacs 的新用户来说 有什么好的教程 参考来学习和熟悉 Emacs 的搜索 替换和正则表达式功能吗 In Emacs press
  • 动态生成的 Perl Moose 访问器

    请参阅以下基于 Moose 的 Perl 代码片段 BusinessClass gt meta gt add attribute Key gt is gt rorw isa gt MooseType lazy gt 0 required g
  • C语言中如何连接两个整数

    Stack Overflow 用许多其他语言回答了这个问题 但没有用 C 语言回答 所以我想我会问 因为我有同样的问题 C语言中如何连接两个整数 Example x 11 y 11 我想要 z 如下 z 1111 其他示例尝试使用字符串来执
  • N层架构中如何维护事务

    我正在 N 层架构中开发应用程序 众所周知 我们需要在插入 更新 删除操作时实现事务 请告诉我如何在 N 层架构的 c net 中使用事务 我的架构是这样的 Applicationform gt middle Layre gt Factor
  • simple_form 带有自定义包装器的自定义输入

    我正在尝试在我的应用程序中为货币进行自定义输入 我有那些 bootstrap 包装器等 我认为它带有 simple form 或 bootstrap gem 所以 我可以做类似的事情 它的工作原理正如预期的那样 问题是 我在很多地方都需要同
  • 登录框架

    想象一下有一个框架提供了一个名为logutils set up 它根据某些配置设置日志记录 应尽早设置日志记录 因为导入库期间发出的警告不应丢失 由于旧方法 if name main 看起来很难看 我们使用控制台脚本入口点来注册main m