shelve(python)真的很奇怪的问题

时间:2010-02-01 23:52:23

标签: python shelve

我创建了一个名为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。

6 个答案:

答案 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)

OverByThere commented on Jul 17, 2018

This seems to be fixable.

简而言之,打开/usr/lib/python3.5/weakref.py并将第109行更改为:

 def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):

第117行到:

_atomic_removal(d, wr.key)

请注意,您需要使用空格而不是制表符,因为这会导致其他错误。