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

问题描述 投票:5回答:6

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

python shelve
6个回答
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跟踪器中打开一个bug!


10
投票

经过几天的脱发后,我终于使用atexit功能取得了成功:

  import atexit
  ...
  cache = shelve.open(path)
  atexit.register(cache.close)

打开后立即注册是最合适的。这适用于多个并发架子。

(关于清晰的python 2.6.5)


2
投票

这确实是一个Python错误,我已经发布了你打开的跟踪器问题的补丁(感谢你这样做)。

问题是shelve的del方法调用它的close方法,但是如果shelve模块已经通过清理,则close方法会失败并显示您看到的消息。

您可以通过在g.shelf.close之后添加'del g.shelf'来避免代码中的消息。只要g.shelf是对架子的唯一引用,这将导致CPython在解释器清理阶段之前立即调用shelve的del方法,从而避免错误消息。


1
投票

它似乎是shelve模块注册的关闭函数中的一个例外。 “忽略”部分来自关闭系统,并且可能会根据Issue 6294的某些时间改进其措辞。我仍然希望得到关于如何消除异常本身的答案,尽管......


1
投票

对我来说,一个简单的shelve.close()在一个未闭合的人做了这个工作。

shelve.open('somefile')返回一个“用于读写的持久字典”对象,我在整个应用程序的运行时使用它。当我终止应用程序时,我收到了所提到的“TypeError”异常。我在终止序列中调用了一个'close()'调用,这似乎解决了这个问题。

例如shelveObj = shelve.open('fileName')... shelveObj.close()


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)

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

© www.soinside.com 2019 - 2024. All rights reserved.