我创建了一个名为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。
答案 0 :(得分:10)
我认为你在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跟踪器中打开一个错误!
答案 1 :(得分:9)
经过几天脱发后,我终于使用了atexit功能取得了成功:
import atexit
...
cache = shelve.open(path)
atexit.register(cache.close)
打开后立即注册是最合适的。这适用于多个并发架子。
(关于清晰的python 2.6.5)
答案 2 :(得分:2)
这确实是一个Python错误,我已经发布了你打开的跟踪器问题的补丁(感谢你这样做)。
问题是shelve的 del 方法调用了它的close方法,但是如果shelve模块已经通过清理,则close方法会因你看到的消息而失败。
您可以通过在g.shelf.close之后添加'del g.shelf'来避免代码中的消息。只要g.shelf是对架子的唯一引用,这将导致CPython在解释器清理阶段之前立即调用shelve的 del 方法,从而避免出现错误消息。
答案 3 :(得分:1)
shelve
模块注册的关闭函数似乎是一个例外。 “忽略”部分来自关闭系统,并且可能会在Issue 6294的某个时间改进其措辞。我仍然希望得到关于如何消除异常本身的答案,但是......
答案 4 :(得分:0)
对我来说,一个关于未闭合的人的简单shelve.close()
就完成了这项工作。
shelve.open('somefile')返回一个“用于读写的持久字典”对象,我在整个应用程序的运行时使用它。 当我终止应用程序时,我收到了所提到的“TypeError”异常。 我在终止序列中调用了一个'close()'调用,这似乎解决了这个问题。
e.g。 shelveObj = shelve.open('fileName') ... shelveObj.close()
答案 5 :(得分:0)
简而言之,打开/usr/lib/python3.5/weakref.py并将第109行更改为:
def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):
第117行到:
_atomic_removal(d, wr.key)
请注意,您需要使用空格而不是制表符,因为这会导致其他错误。