【问题标题】:Why doesn't Python exit from a raised exception when executed with an absolute path?为什么 Python 在使用绝对路径执行时不会退出引发的异常?
【发布时间】:2012-10-12 19:15:15
【问题描述】:

已解决:重新启动机器似乎已解决问题。如果问题再次出现,我会更新。

我遇到了一个问题,即Python2.6 在引发异常后挂起,特别是在使用绝对路径 (/home/user/bar/foo.py) 调用 foo.py 时。然后我需要ctrl+c 退出程序。如果从bar 目录中调用./foo.py 或从根目录调用./home/user/bar/foo.py,程序将正确终止。

foo.py:

#!/usr/bin/env python2.6
print 'begin'
x = [0, 1, undefined]
print 'x'

#!/usr/bin/env python2.6
print 'begin'
raise Exception('stopping here')

我还可能提到sys.exit() 工作正常,没有问题。

#!/usr/bin/env python2.6
import sys
print 'begin'
sys.exit(0)

无法终止程序的异常发生了什么?这可能特定于我的配置。我应该从哪里开始寻找解决方案?

编辑:execfile('/home/user/bar/foo.py') 在交互模式下运行良好。此外,运行nohup /home/user/bar/foo.py & 会导致必须终止的挂起进程。

运行 CentOS 6.3 版(最终版)。这个问题并不总是存在。这只是大约一个月前的一个周末才开始的(当时我没有使用机器)。

更新:使用 GDB 进行调试,回溯指向 libpthread.so.0

#0  0x000000364340e890 in __connect_nocancel () from /lib64/libpthread.so.0
#1  0x00007ffff18960d8 in ?? () from /usr/lib64/python2.6/lib-dynload/_socketmodule.so
#2  0x00007ffff189815c in ?? () from /usr/lib64/python2.6/lib-dynload/_socketmodule.so
#3  0x00007ffff7d0a706 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.6.so.1.0
#4  0x00007ffff7d0c797 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.6.so.1.0
#5  0x00007ffff7d0abe4 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.6.so.1.0
#6  0x00007ffff7d0bccf in PyEval_EvalFrameEx () from /usr/lib64/libpython2.6.so.1.0
#7  0x00007ffff7d0bccf in PyEval_EvalFrameEx () from /usr/lib64/libpython2.6.so.1.0
#8  0x00007ffff7d0c797 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.6.so.1.0
#9  0x00007ffff7c9adb0 in ?? () from /usr/lib64/libpython2.6.so.1.0
#10 0x00007ffff7c70303 in PyObject_Call () from /usr/lib64/libpython2.6.so.1.0
#11 0x00007ffff7d04dd3 in PyEval_CallObjectWithKeywords () from /usr/lib64/libpython2.6.so.1.0
#12 0x00007ffff7d28cd2 in PyErr_PrintEx () from /usr/lib64/libpython2.6.so.1.0
#13 0x00007ffff7d29297 in PyRun_SimpleFileExFlags () from /usr/lib64/libpython2.6.so.1.0
#14 0x00007ffff7d35c32 in Py_Main () from /usr/lib64/libpython2.6.so.1.0
#15 0x000000364281ecdd in __libc_start_main () from /lib64/libc.so.6
#16 0x0000000000400649 in _start ()

有人知道这是什么意思吗?

【问题讨论】:

  • 您是否使用任何其他版本的 Python 对此进行了测试,以查看问题是否仅限于 2.6?这将有助于重现错误。
  • 另外,我刚刚在 Python 2.4.3、2.6.5 和 2.7.3 上对此进行了测试,但无法让程序挂起。您系统上的其他东西(配置设置或其他东西)必须以某种方式做出贡献。
  • 我在这台机器上没有 sudo 权限来尝试另一个版本。
  • 在 Python 2.4.3/RHEL 5.5 上测试,无重现
  • 你有类似配置的盒子吗?你能在其他盒子上重现这个问题吗?

标签: python exception-handling


【解决方案1】:

这个确切的问题在 RHEL 6 机器上一直困扰着我一段时间。在某些情况下,异常会导致挂起。事实上,我能够逐字记录您的代码并重现症状。

感谢 abrtd 的回答,我确定安装了 abrt-addon-python 包,它将 abrt_exception_handler.py 放入站点包位置,并在 python 启动期间调用。该文件覆盖了 sys.excepthook 函数,该函数使用套接字联系 abrt 守护进程。请参阅ABRT Project Doc 了解更多信息。

我验证了在 python 调用中添加 -S 可以防止挂起。然而,这不是一个好的解决方案,因为 -S 选项会阻止在启动时导入所有站点包。

更好的解决方案是在您的 python 代码中添加以下内容:

import sys
sys.excepthook = sys.__excepthook__

恢复原始异常钩子并防止挂起。

【讨论】:

    【解决方案2】:
    • 请检查sys.path 是否有非绝对目录。
    • 你可以随时break into it with a debugger, e.g. gdb
    • 有时我在PYTHONSTARTUP 中有一些东西,这会导致交互式解释器执行不同的操作...
    • strace也可以做你的朋友

    【讨论】:

      【解决方案3】:
      • 重启机器。

      在全能管理员的帮助下,我能够重新启动机器。一切都很好。如果问题再次出现,我会更新问题。

      【讨论】:

        【解决方案4】:

        我跟踪了这​​个问题。它正在尝试写入被 abrtd 打开的套接字。

        重新启动 abrtd “修复”了该问题。这就是机器重启起作用的原因。不过我还没有找到问题的根本原因。

        【讨论】:

          猜你喜欢
          • 2012-11-27
          • 1970-01-01
          • 1970-01-01
          • 2011-10-13
          • 1970-01-01
          • 2018-05-04
          • 2018-02-18
          • 2018-12-26
          • 1970-01-01
          相关资源
          最近更新 更多