Lebensdauermerkmale von Python-Objekten

Hinweis: Wenn Sie einen (nicht detaillierten) Bibliothekscode kennen, der genau das tut, was ich möchte, klären Sie bitte einen C / C ++ - Programmierer auf. Ich akzeptiere dies als Antwort.

Ich habe eine globale Variable auf eine Instanz der folgenden Klasse festgelegt. Es soll mir erlauben, einige manuelle Unterbrechungspunkte zu setzen, um einige schnell und schmutzig zu platzierenprintf Style-Debug-Punkte in einer Scrapy-Spinne (Ich muss speziell brechen, wenn bestimmte Kriterien erfüllt sind, um einen Parser zu optimieren. Es gibt einige extrem seltene Anomalien bei Eingabedaten.) - Angepasst vondiese.

OS ist OS X 10.8.

import termios, fcntl, sys, os

class DebugWaitKeypress(object):
    def __init__(self):
        self.fd = sys.stdin.fileno()
        self.oldterm = termios.tcgetattr(self.fd)
        self.newattr = termios.tcgetattr(self.fd)
        self.newattr[3] = self.newattr[3] & ~termios.ICANON & ~termios.ECHO
        termios.tcsetattr(self.fd, termios.TCSANOW, self.newattr)

        self.oldflags = fcntl.fcntl(self.fd, fcntl.F_GETFL)
        fcntl.fcntl(self.fd, fcntl.F_SETFL, self.oldflags | os.O_NONBLOCK)

    def wait(self):
        sys.stdin.read(1)

    def __del__(self):
        print "called del"
        termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.oldterm)
        fcntl.fcntl(self.fd, fcntl.F_SETFL, self.oldflags)

Wenn ich Strg-C drücke und der Prozess abläuft, erhalte ich die folgende Ausnahme:

Exception AttributeError: "'NoneType' object has no attribute 'tcsetattr'" in <bound method DebugWaitKeypress.__del__ of <hon.spiders.custom_debug.DebugWaitKeypress object at 0x108985e50>> ignored

Ich vermisse etwas über die Mechanik der Objektlebensdauer, denke ich? Wie kann man Abhilfe schaffen? AFAIK alle Klasseninstanzen sollten zerstört werden, bevor der importierte Code es tut, nicht wahr? in umgekehrter Reihenfolge der Deklaration / Definition.

Ich würde das einfach ignorieren, wenn das Terminal nach dem Beenden des Prozesses nicht kaputt wäre: D

bearbeiten:

Delians Kommentar zu Seths Antwort ließ mich verstehen, dass ich ein C verwenden mussmain() Like-Funktion oder jede andere Funktion / Generator, die als Root-Funktion dominiert und den Kontext dort initialisiert. Auf diese Weise, wenn der Prozess abläuft__exit__ Methode des Context Managers wird aufgerufen. Und ich muss den Terminal-Stream nicht auf jedem neu programmierenwait() Anruf.

Obwohl die Kosten für die Neuprogrammierung möglicherweise unerheblich sind, ist es gut zu wissen, wie man diese wesentlichen C / C ++ - Semantiken in Python einsetzen würde.

2 bearbeiten:

Twisted (welches Scrapy benutzt) macht beim Spielen mit stdin kaputt. Also musste ich das Problem mit der Datei IO lösen.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage