2010-02-01 6 views
5

ich eine Datei erstellen foo_module.py enthält den folgenden Code genannt:wirklich seltsam Problem mit shelve (Python)

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") 

Neben diese Datei ich ein Verzeichnis foo_package genannt schaffen, als eine leere __init__.py Datei und eine Datei namens g.py dass gerade enthält:

class g: 
    pass 

Nun, wenn ich foo_module.py laufen bekomme ich eine seltsame Fehlermeldung:

Exception TypeError: "'NoneType' object is not callable" in ignored

Aber dann, wenn ich das Verzeichnis foo_package-foo, umbenennen und die Importzeile in foo_module.py ändern, ich bekomme keine Fehler. WTF geht hier vor?

Ausführen von Python 2.6.4 auf WinXP.

Antwort

10

Ich denke, Sie haben einen kleinen Fehler in 2.6.4 Code im Zusammenhang mit der Bereinigung am Ende des Programms getroffen. Wenn Sie laufen python -v Sie genau, an welchem ​​Punkt des Bereinigungs sehen können der Fehler kommt:

# cleanup[1] foo_package.g 
Exception TypeError: "'NoneType' object is not callable" in ignored 

Python setzt Verweise auf None während der Bereinigung am Ende des Programms, und es sieht aus wie es ist immer verwirrt über den Status g.shelf. Als Workaround können Sie g.shelf = None nach dem close setzen. Ich würde auch empfehlen, einen Bug in Pythons Bug Tracker zu öffnen!

+2

Die Problemumgehung funktioniert, danke. Hier ist der Fehlerbericht: http://bugs.python.org/issue7835 –

1

Es scheint eine Ausnahme in einer Shutdown-Funktion zu sein, die vom Modul shelve registriert wird. Der "ignorierte" Teil kommt vom Shutdown-System und könnte irgendwann seinen Wortlaut verbessern, per Issue 6294. Ich hoffe immer noch auf eine Antwort, wie man die Ausnahme selbst beseitigt, aber ...

2

Dies ist in der Tat ein Python-Bug, und ich habe einen Patch auf das Tracker-Problem gepostet, das Sie geöffnet haben (danke dafür).

Das Problem ist, dass del-Methode von shelve seine Close-Methode aufruft, aber wenn das Shelve-Modul bereits bereinigt wurde, schlägt die Close-Methode mit der Nachricht fehl, die Sie sehen.

Sie können die Nachricht in Ihrem Code vermeiden, indem Sie "del g.shelf" nach g.shelf.close hinzufügen. Solange g.shelf der einzige Verweis auf das Shelf ist, führt dies dazu, dass CPython die Methode del sofort vor der Interpreter-Bereinigungsphase aufruft und somit die Fehlermeldung vermeidet.

8

Nach Tagen des Haarausfalls, ich hatte schließlich Erfolg eine atexit Funktion:

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

Es ist am besten geeignet Recht nach dem Öffnen zu registrieren. Dies funktioniert mit mehreren gleichzeitigen Regalen.

(Python 2.6.5 auf luzide)

+5

'atexit.register (cache.close)' Keine Notwendigkeit für ein Lambda ... –

0

für mich eine einfache shelve.close() auf einem nicht geschlossenen man hat den Job.

Regal.open ('somefile') gibt ein "persistentes Wörterbuch zum Lesen und Schreiben" -Objekt zurück, das ich während der Laufzeit der App verwendet habe. Wenn ich die App beendet habe, habe ich die "TypeError" -Ausnahme wie erwähnt erhalten. Ich habe einen 'close()' Anruf in meiner Terminierungssequenz ausgelöst und das schien das Problem zu beheben.

z.B. shelveObj = shelve.open ('Dateiname') ... shelveObj.close()

+0

Würde es Ihnen etwas ausmachen, die Antwort Bit mehr für Kollegen Programmierer zu erweitern verstehe, wie es hilft, das Problem zu lösen. – Daenarys