处理Python脚本的绝对/相对路径时的异常处理
我有一个没有shebang的python脚本(这很重要)。当我用相对路径运行它时,一切都正常,异常信息会直接显示在终端上:
$ python -V
Python 2.6.6
$ cat 1.py
import os
print os.getcwd()
a=b
print c
$ python ./1.py
/home/user
Traceback (most recent call last):
File "./1.py", line 5, in <module>
a=b
NameError: name 'b' is not defined
$
但是,当我用绝对路径指定脚本时,只有在按下Control-C时才会抛出异常(注意代码片段中Traceback部分前的^C符号):
$ python /home/user/1.py
/home/user
^CTraceback (most recent call last):
File "/home/v-yyushyn/1.py", line 5, in <module>
a=b
NameError: name 'b' is not defined
$
起初,我以为这种行为是因为“绝对路径”在子shell中运行,但经过简单调查后我发现这两种启动方式都是在同一个shell中运行的。
当然,可以加上shebang,这样就可以在运行脚本时不需要指定解释器。但我很好奇为什么在使用绝对路径和相对路径时,行为会有所不同。
有没有人对此有什么建议?谢谢
更新:python -v /home/user/1.py
# installing zipimport hook
import zipimport # builtin
# installed zipimport hook
# /usr/lib64/python2.6/site.pyc matches /usr/lib64/python2.6/site.py
import site # precompiled from /usr/lib64/python2.6/site.pyc
# /usr/lib64/python2.6/os.pyc matches /usr/lib64/python2.6/os.py
import os # precompiled from /usr/lib64/python2.6/os.pyc
import errno # builtin
import posix # builtin
# /usr/lib64/python2.6/posixpath.pyc matches /usr/lib64/python2.6/posixpath.py
import posixpath # precompiled from /usr/lib64/python2.6/posixpath.pyc
# /usr/lib64/python2.6/stat.pyc matches /usr/lib64/python2.6/stat.py
import stat # precompiled from /usr/lib64/python2.6/stat.pyc
# /usr/lib64/python2.6/genericpath.pyc matches /usr/lib64/python2.6/genericpath.py
import genericpath # precompiled from /usr/lib64/python2.6/genericpath.pyc
# /usr/lib64/python2.6/warnings.pyc matches /usr/lib64/python2.6/warnings.py
import warnings # precompiled from /usr/lib64/python2.6/warnings.pyc
# /usr/lib64/python2.6/linecache.pyc matches /usr/lib64/python2.6/linecache.py
import linecache # precompiled from /usr/lib64/python2.6/linecache.pyc
# /usr/lib64/python2.6/types.pyc matches /usr/lib64/python2.6/types.py
import types # precompiled from /usr/lib64/python2.6/types.pyc
# /usr/lib64/python2.6/UserDict.pyc matches /usr/lib64/python2.6/UserDict.py
import UserDict # precompiled from /usr/lib64/python2.6/UserDict.pyc
# /usr/lib64/python2.6/_abcoll.pyc matches /usr/lib64/python2.6/_abcoll.py
import _abcoll # precompiled from /usr/lib64/python2.6/_abcoll.pyc
# /usr/lib64/python2.6/abc.pyc matches /usr/lib64/python2.6/abc.py
import abc # precompiled from /usr/lib64/python2.6/abc.pyc
# /usr/lib64/python2.6/copy_reg.pyc matches /usr/lib64/python2.6/copy_reg.py
import copy_reg # precompiled from /usr/lib64/python2.6/copy_reg.pyc
# /usr/lib/python2.6/site-packages/abrt_exception_handler.pyc matches /usr/lib/python2.6/site-packages/abrt_exception_handler.py
import abrt_exception_handler # precompiled from /usr/lib/python2.6/site-packages/abrt_exception_handler.pyc
import encodings # directory /usr/lib64/python2.6/encodings
# /usr/lib64/python2.6/encodings/__init__.pyc matches /usr/lib64/python2.6/encodings/__init__.py
import encodings # precompiled from /usr/lib64/python2.6/encodings/__init__.pyc
# /usr/lib64/python2.6/codecs.pyc matches /usr/lib64/python2.6/codecs.py
import codecs # precompiled from /usr/lib64/python2.6/codecs.pyc
import _codecs # builtin
# /usr/lib64/python2.6/encodings/aliases.pyc matches /usr/lib64/python2.6/encodings/aliases.py
import encodings.aliases # precompiled from /usr/lib64/python2.6/encodings/aliases.pyc
# /usr/lib64/python2.6/encodings/utf_8.pyc matches /usr/lib64/python2.6/encodings/utf_8.py
import encodings.utf_8 # precompiled from /usr/lib64/python2.6/encodings/utf_8.pyc
Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23)
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
/home/user
/usr/lib64/python2.6/os.pyc
/home/user/1.py
False
<function <lambda> at 0x7fa22e784c08>
dlopen("/usr/lib64/python2.6/lib-dynload/syslog.so", 2);
import syslog # dynamically loaded from /usr/lib64/python2.6/lib-dynload/syslog.so
# /usr/lib64/python2.6/traceback.pyc matches /usr/lib64/python2.6/traceback.py
import traceback # precompiled from /usr/lib64/python2.6/traceback.pyc
# /usr/lib64/python2.6/socket.pyc matches /usr/lib64/python2.6/socket.py
import socket # precompiled from /usr/lib64/python2.6/socket.pyc
dlopen("/usr/lib64/python2.6/lib-dynload/_socketmodule.so", 2);
import _socket # dynamically loaded from /usr/lib64/python2.6/lib-dynload/_socketmodule.so
dlopen("/usr/lib64/python2.6/lib-dynload/_ssl.so", 2);
import _ssl # dynamically loaded from /usr/lib64/python2.6/lib-dynload/_ssl.so
dlopen("/usr/lib64/python2.6/lib-dynload/cStringIO.so", 2);
import cStringIO # dynamically loaded from /usr/lib64/python2.6/lib-dynload/cStringIO.so
^CTraceback (most recent call last):
File "/home/user/1.py", line 10, in <module>
a=b
NameError: name 'b' is not defined
# clear __builtin__._
# clear sys.path
# clear sys.argv
# clear sys.ps1
# clear sys.ps2
# clear sys.exitfunc
# clear sys.exc_type
# clear sys.exc_value
# clear sys.exc_traceback
# clear sys.last_type
# clear sys.last_value
# clear sys.last_traceback
# clear sys.path_hooks
# clear sys.path_importer_cache
# clear sys.meta_path
# clear sys.flags
# clear sys.float_info
# restore sys.stdin
# restore sys.stdout
# restore sys.stderr
# cleanup __main__
# cleanup[1] cStringIO
# cleanup[1] encodings
# cleanup[1] site
# cleanup[1] syslog
# cleanup[1] abc
# cleanup[1] _codecs
# cleanup[1] _warnings
# cleanup[1] zipimport
# cleanup[1] encodings.utf_8
# cleanup[1] codecs
# cleanup[1] socket
# cleanup[1] signal
# cleanup[1] traceback
# cleanup[1] posix
# cleanup[1] encodings.aliases
# cleanup[1] exceptions
# cleanup[1] abrt_exception_handler
# cleanup[1] _ssl
# cleanup[1] _socket
# cleanup[2] copy_reg
# cleanup[2] posixpath
# cleanup[2] errno
# cleanup[2] _abcoll
# cleanup[2] types
# cleanup[2] genericpath
# cleanup[2] stat
# cleanup[2] warnings
# cleanup[2] UserDict
# cleanup[2] os.path
# cleanup[2] linecache
# cleanup[2] os
# cleanup sys
# cleanup __builtin__
# cleanup ints: 19 unfreed ints
# cleanup floats
1 个回答
3
这个客户端安装了一个叫做 abrt
的自动错误报告工具。它会捕捉程序中的异常,并把这些异常发送到一个专门的进程去追踪崩溃情况。这个工具在CentOS和Redhat系统上很常见(你可以查看 Redhat的文档)。
问题出在这个进程上,它会卡住,需要你用中断来绕过它。
你可以查看 abrt
的配置文档,了解它在做什么,并调整设置以避免它卡住。abrt
的常见问题解答也可能对你有帮助;那里有一些命令可以用来检查服务的状态。
从 hook abrt
安装的代码中可以看到,带有相对路径的脚本会被忽略;它只处理带有绝对路径的脚本(比如 /home/user/1.py
),这就是你只在这种情况下遇到问题的原因。
同样的代码显示,它会把信息记录到 syslog
中;默认情况下,这些信息会出现在 /var/log/user.log
中;你可以在那里查找脚本的文件名(1.py
)。
很可能是与 abrtd
守护进程的套接字连接出现了问题。套接字卡住的原因可能有很多,比如 网络固件故障等。