2009-05-24 5 views
14

Nachdem ich gerade meine Haare wegen eines Unterschieds gezogen habe, würde ich gerne wissen, was der Unterschied wirklich in Python 2.5 ist.Python 'mit' Aussage versus 'mit .. als'

Ich hatte zwei Blöcke Code (dbao.getConnection() gibt eine MySQLdb-Verbindung zurück).

conn = dbao.getConnection() 
with conn: 
    # Do stuff 

Und

with dbao.getConnection() as conn: 
    # Do stuff 

dachte ich, diese die gleiche Wirkung haben würden, aber offenbar nicht als die conn Aufgabe der letzteren Version ein Cursor war. Woher kam der Cursor und ist gibt es eine Möglichkeit, die Initialisierung der Variablen und mit Anweisung irgendwie zu kombinieren?

+4

Die zweite Version initialisiert eine Variable, conn. Welches eigentliche Problem hast du? Was hat anders funktioniert? Welchen Fehler hast du bekommen? Können Sie eine Ausgabe hinzufügen, um das Problem zu zeigen? –

+0

Entschuldigung. Dachte, es wäre aus der Beschreibung klar geworden. dbao.getConnection() gibt eine MySQLdb-Verbindung zurück, so dass conn = dbao.getConnection() dazu führt, dass ein Conn ein Connection-Objekt ist, während "mit dbao.getConnection() as conn" dazu führt, dass conn ein Cursor-Objekt ist.Die Fehlermeldung war, dass Conn im letzten Fall keine Rollback-Methode hatte, die es nicht hätte haben sollen, da es ein Cursor war. –

Antwort

1

Die with-Anweisung dient zum Beispiel dazu, sicherzustellen, dass die Transaktion ordnungsgemäß gestartet und gestoppt wird.

Im Falle von Datenbank-Verbindungen in Python, denke ich, ist die natürliche Sache zu tun, einen Cursor am Anfang der With-Anweisung zu erstellen und dann Commit oder Rollback der Transaktion am Ende davon.

Die beiden Blöcke, die Sie angegeben haben, sind aus Sicht der Anweisung identisch. Sie können das so zum ersten genauso hinzufügen und den Cursor bekommen.

Sie müssen überprüfen, wie die Unterstützung in dem Objekt implementiert ist, mit dem Sie sie verwenden.

Siehe http://docs.python.org/whatsnew/2.5.html#pep-343-the-with-statement

29

Es kann ein wenig verwirrend auf den ersten Blick, aber

with babby() as b: 
    ... 

ist nicht entspricht

b = babby() 
with b: 
    ... 

Um zu sehen, warum hier, wie der Kontext-Manager implementiert werden würde:

class babby(object): 
    def __enter__(self): 
     return 'frigth' 

    def __exit__(self, type, value, tb): 
     pass 

Im ersten Fall der Name b wird an das gebunden, was von der __enter__-Methode des Kontextmanagers zurückgegeben wird. Dies ist oft der Kontextmanager selbst (zum Beispiel für Dateiobjekte), muss es aber nicht sein; In diesem Fall ist es die Zeichenfolge 'frigth', und in Ihrem Fall ist es der Datenbankcursor.

Im zweiten Fall ist b das Context Manager-Objekt selbst.

+0

In solchen Zeiten wünschte ich, ich könnte zwei Antworten geben. : | –

+1

@Mikko: IMHO das ist das bessere - wenn nicht aus einem anderen Grund als es detaillierter ist und diskutiert die Unterschiede - Antwort und sollte die akzeptierte sein. – martineau

+0

@martineau: Da wir alte Kommentare kommentieren! Ja, diese Antwort ist detaillierter und diskutiert die Unterschiede. Es gibt mehr Hintergrundinformationen und in diesem Sinne ist es besser. Aber als Antwort ist es auf den Kopf gestellt. Die angenommene Antwort schafft es, die spezifische Frage in den (ersten) zwei Zeilen zu beantworten. Mit diesem muss ich Beispielfälle usw. durchlesen, bevor ich eine Antwort auf die Frage erhalte. Eine perfekte Antwort hätte die akzeptierte Antwort als erster Absatz gefolgt von diesem. Hintergrundinformationen sind nett, aber manchmal ist es auch erfrischend, nur die Antwort zu bekommen. –