Problema realmente estranho com Shelve (Python)
Pergunta
Eu crio um arquivo chamado foo_module.py
contendo o seguinte código:
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")
Ao lado desse arquivo, crio um diretório chamado foo_package
do que contém um vazio __init__.py
arquivo e um arquivo chamado g.py
que apenas contém:
class g:
pass
Agora quando eu corro foo_module.py
Eu recebo uma mensagem de erro estranha:
Exception TypeError: "'NoneType' object is not callable" in ignored
Mas então, se eu renomear o diretório de foo_package
para foo
, e mudar a linha de importação em foo_module.py
, Eu não recebo nenhum erro. WTF está acontecendo aqui?
Executando o Python 2.6.4 no WinXP.
Solução
Eu acho que você acertou um bug menor no código do 2.6.4 relacionado à limpeza no final do programa. Se você correr python -v
Você pode ver exatamente em que ponto da limpeza o erro vem:
# cleanup[1] foo_package.g
Exception TypeError: "'NoneType' object is not callable" in ignored
Python define referências a None
durante a limpeza no final do programa, e parece que está ficando confuso sobre o status de g.shelf
. Como solução alternativa, você pode definir g.shelf = None
depois de close
. Eu também recomendaria abrir um bug no rastreador de bugs do Python!
Outras dicas
Após dias de perda de cabelo, finalmente tive sucesso usando uma função Atexit:
import atexit
...
cache = shelve.open(path)
atexit.register(cache.close)
É mais apropriado se registrar logo após a abertura. Isso funciona com várias prateleiras simultâneas.
(Python 2.6.5 em Lucid)
Este é realmente um bug python, e eu publiquei um patch no problema do rastreador que você abriu (obrigado por fazer isso).
O problema é que Shelve's del O método chama seu método de perto, mas se o módulo Shelve já tiver passado pela limpeza, o método de fechamento falhará com a mensagem que você vê.
Você pode evitar a mensagem em seu código adicionando 'del G.shelf' após G.shelf.close. Enquanto G. prateleira for a única referência à prateleira, isso resultará em Cpython chamando o Shelve's del Método imediatamente, antes da fase de limpeza do intérprete e, assim, evite a mensagem de erro.
Parece ser uma exceção em uma função de desligamento registrada pelo shelve
módulo. A parte "ignorada" é do sistema de desligamento e pode melhorar sua redação em algum momento, por Edição 6294. Ainda estou esperando uma resposta sobre como eliminar a exceção em si, no entanto ...
para mim um simples shelve.close()
em um não deslizado fez o trabalho.
Shelve.open ('SomeFile') retorna um objeto "Dicionário persistente para ler e escrever" que eu usei ao longo do tempo de execução do aplicativo. Quando encerrei o aplicativo, recebi a exceção "TypeError", conforme mencionado. Eu coloquei uma chamada 'Close ()' na minha sequência de rescisão e isso parecia resolver o problema.
por exemplo, Shelveobj = shelve.open ('nome do arquivo') ... Shelveobj.close ()
Overby, comentou em 17 de julho de 2018
Em curta open /usr/lib/python3.5/weakref.py e altere a linha 109 para:
def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):
E linha 117 para:
_atomic_removal(d, wr.key)
Observe que você precisa fazer isso com espaços, não guias, pois isso causará outros erros.