我创建了一个名为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
时,我得到一个奇怪的错误消息:
Exception TypeError: "'NoneType' object is not callable" in ignored
但是,如果我将目录从foo_package
重命名为foo
,并更改foo_module.py
中的导入行,我不会收到任何错误。 Wtf在这里发生了什么?
在WinXP上运行Python 2.6.4。
我认为你在2.6.4的程序结束时与清理相关的代码中遇到了一个小错误。如果运行python -v
,您可以准确地看到错误发生的清理点:
# cleanup[1] foo_package.g
Exception TypeError: "'NoneType' object is not callable" in ignored
Python在程序结束时的清理过程中设置了对None
的引用,看起来它对g.shelf
的状态感到困惑。作为一种解决方法,你可以在g.shelf = None
之后设置close
。我还建议在Python的bug跟踪器中打开一个bug!
经过几天的脱发后,我终于使用atexit功能取得了成功:
import atexit
...
cache = shelve.open(path)
atexit.register(cache.close)
打开后立即注册是最合适的。这适用于多个并发架子。
(关于清晰的python 2.6.5)
这确实是一个Python错误,我已经发布了你打开的跟踪器问题的补丁(感谢你这样做)。
问题是shelve的del方法调用它的close方法,但是如果shelve模块已经通过清理,则close方法会失败并显示您看到的消息。
您可以通过在g.shelf.close之后添加'del g.shelf'来避免代码中的消息。只要g.shelf是对架子的唯一引用,这将导致CPython在解释器清理阶段之前立即调用shelve的del方法,从而避免错误消息。
它似乎是shelve
模块注册的关闭函数中的一个例外。 “忽略”部分来自关闭系统,并且可能会根据Issue 6294的某些时间改进其措辞。我仍然希望得到关于如何消除异常本身的答案,尽管......
对我来说,一个简单的shelve.close()
在一个未闭合的人做了这个工作。
shelve.open('somefile')返回一个“用于读写的持久字典”对象,我在整个应用程序的运行时使用它。当我终止应用程序时,我收到了所提到的“TypeError”异常。我在终止序列中调用了一个'close()'调用,这似乎解决了这个问题。
例如shelveObj = shelve.open('fileName')... shelveObj.close()
简而言之,打开/usr/lib/python3.5/weakref.py并将第109行更改为:
def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):
并且第117行到:
_atomic_removal(d, wr.key)
请注意,您需要使用空格而不是制表符,因为这会导致其他错误。