【问题标题】:Prevent Python script to fail防止 Python 脚本失败
【发布时间】:2020-01-16 02:23:40
【问题描述】:

我有一个 python 脚本,它将在树莓上 24/7 运行至少五个月,如果出现任何问题,我无法访问该东西以重新启动它。它使用各种库连接到 sql 数据库、无线 RFID 阅读器等。

基本上是几十行定义函数,通过usb/serial将raspberry连接到设备,然后是一个大的while True:循环。

我想确保如果发生错误,代码将继续运行(或重试直到没有错误发生)并且不会卡在错误上。我读到我可以使用try: Except: but it seems to be not be recommended

您是否有任何资源可以让我学习如何使 Python 脚本在发生任何情况时都防弹,或者有关如何做到这一点的想法?

【问题讨论】:

  • 没办法,因为硬件很可能出故障。
  • 这真的取决于你期望(并且想要处理)什么样的失败,但通常我会说你应该离开那个“保持活力”/自动重启/......在你的python代码中而是让您的发行版处理它。启动该过程并在它终止时继续这样做。根据您的 init 及其能力,您可能已经获得了该功能并且只需注册另一个服务。这也可能涵盖正在重启的主机,而您实际上无法在脚本本身内做任何事情。

标签: python try-catch except


【解决方案1】:

try 是一个很好的资源。

在这里,我尝试调用一个环境变量。如果没有设置,我会尝试设置它。如果我不能设置它,我会让用户知道发生了什么,这样他们就不会害怕。

try:
    os.environ['R_HOME']
except:
    print("""
        \u2717 ERROR: The default Jupyter/Conda path for R, `os.environ['R_HOME']` is undefined, cannot print it's path.
        This should have been set when running the Docker image like so:
        `-e R_HOME=/opt/conda/lib/R`
    """)
    try:
        print("\u0009Attempting to set `os.environ['R_HOME']` manually...")
        os.environ['R_HOME'] = '/opt/conda/lib/R'
    except:
        print("\u0009Failed to set `R_HOME` this must not be a conda managed jupyter environment with both R and Python kernels.")
    else:
        print("\u0009\u2713 -- 'R_HOME' is now `" + os.environ['R_HOME'] + "`." ) 
else:
    print("\u0009\u2713 -- The path of the Jupyter R enviroment being accessed by `rpy2` is '" + os.environ['R_HOME'] + "'.\n")

【讨论】:

    【解决方案2】:

    systemdmonitrunit 注册它。这些是服务管理器,当他们正在观看的程序死机时,会注意到它的缺失并使用您提供的命令行机制重新启动它。了解它们可能有点棘手(并提供 pid 或其他方案来“签署”python 脚本的存在),但这是它们的设计目的。我自己很喜欢 runit,但 systemd(也许很不幸)出现在大多数 Linux 发行版中。

    你所依赖的其他东西,不仅仅是你的脚本,可能也需要类似的监视,尽管通常像数据库服务器这样的东西从一开始就已经配置好了自己。

    过去确保良好的编码卫生、质量和测试,在任何程序本身(使用 Python 或其他语言)中解决您的需求类型是一种低效且错误地令人放心的追求。高可用性机制依赖于第二个程序重新启动第一个程序的工作/主或同级系统。不是靠自己的编程技能“希望最好”。

    正如@Ondrej K 所说,这最好留给你的发行版 - init 是另一个专门用于此的框架。对于一个配置良好的 Linux 系统来说,五个月的正常运行时间是完全合理的期望。而且,正如他所指出的,这些机制还包括系统重启。

    要明确一点:您仍然需要确保您的程序在所有情况下都能自行处理 - 例如,如果它卡在写权限错误上,循环重启将无济于事。

    附:如果 Pi 已联网,如果您需要访问它,ssh 可能会有所帮助。

    【讨论】:

      【解决方案3】:

      实际上,try: except: 块应该没问题,但需要注意的是,您应该确保在 except: 块中记录错误和堆栈跟踪;在您的情况下,这可能只是意味着打印到保存其输出的控制台,将日志保存到日志文件,和/或让您的脚本向您发送电子邮件。例如:

      导入回溯

      try:
          #Code that may cause an exception.
      except Exception as e:
          print(e)
          print(traceback.format_exec())
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-18
        • 1970-01-01
        • 2015-01-25
        • 1970-01-01
        • 2015-09-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多