关于shelve(Python)的奇怪问题
我创建了一个叫做 foo_module.py
的文件,里面有以下代码:
import shelve, whichdb, os
from foo_package.g import g
g.shelf = shelve.open("foo_path")
g.shelf.close()
print whichdb.whichdb("foo_path") # => dbhash
os.remove("foo_path")
然后我在这个文件旁边创建了一个叫做 foo_package
的文件夹,里面有一个空的 __init__.py
文件,还有一个叫 g.py
的文件,里面只包含:
class g:
pass
现在,当我运行 foo_module.py
的时候,出现了一个奇怪的错误信息:
异常类型错误:"'NoneType' 对象不可调用" 被忽略
但是,如果我把文件夹的名字从 foo_package
改成 foo
,并且在 foo_module.py
中修改导入的那一行,就不会出现任何错误了。这到底是怎么回事?
我在 WinXP 上运行 Python 2.6.4。
6 个回答
这确实是Python的一个bug,我已经在你打开的跟踪问题上提交了修复补丁(谢谢你这么做)。
问题在于,shelve的del方法会调用它的close方法,但如果shelve模块已经完成了清理工作,close方法就会失败,并显示你看到的错误信息。
你可以通过在g.shelf.close之后添加'del g.shelf'来避免这个错误信息。只要g.shelf是唯一指向这个shelf的引用,这样做就会让CPython立即调用shelve的del方法,在解释器的清理阶段之前,从而避免错误信息的出现。
经过几天的纠结,我终于成功地使用了一个叫做 atexit 的函数:
import atexit
...
cache = shelve.open(path)
atexit.register(cache.close)
最好在打开之后立刻注册这个函数。这样在多个同时运行的程序中也能正常工作。
(这是在 lucid 上的 python 2.6.5 版本)
我觉得你在2.6.4版本的代码中遇到了一个小问题,这个问题和程序结束时的清理工作有关。如果你运行 python -v
,你可以看到在清理过程中错误出现的具体时刻:
# cleanup[1] foo_package.g
Exception TypeError: "'NoneType' object is not callable" in ignored
在程序结束时,Python会把一些引用设置为 None
,看起来它对 g.shelf
的状态有些困惑。作为一个临时解决办法,你可以在 close
之后把 g.shelf
设置为 None
。我还建议你在Python的错误追踪系统中提交一个bug报告!