Alternative zu "dtuple" ?

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Mittwoch 7. März 2007, 21:42

Hallo zusammen,

Mal folgende Frage: Um mir den Umgang mit den Zeilen (Rows), die ich aus
einer SQL-Abfrage zurückbekomme, etwas zu erleichtern verwende ich "dtuple", damit ich nicht via nackter Indexnummer auf die Elemente zurückgreifen kann sondern direkt via dem Feldnamen.

Irgendwie ist das noch so nicht das wahre, Abfragen wie "select * from ..." bringen "dtuple" wohl durcheinander.. es braucht wohl tatsächlich explizite Abfragen wie "select name, vorname from ... " damit ich dann auch mit "row["name"]" und ähnlichen nach erfolgter Query darauf zugreifen kann.

SQLAlchemy ist aber auch keine Alternative für mich.. Zum einen kommt mir das irgendwie übertrieben vor, und so ein vollständiges Mapping auf Objekte wollte ich auch nicht gleich machen. Noch viel entscheidender: Die Datenbank, um die es geht, gehört nicht zu den von SQLAlchemy unterstützten Datenbanken, Zugriff ist nur via ODBC Treiber möglich (oder JDBC wenn ich das ganze gleich via "Jython" hochziehen würde.. aber so weit wollte ich eigentlich nicht gleich gehen.)

Gibt es denn da nichts anderes? Ich will eigentlich nur halbwegs komfortabel auf die Feldnamen zugreifen können...

Danke im voraus.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 7. März 2007, 23:08

oliver1974 hat geschrieben:Zugriff ist nur via ODBC Treiber möglich
Hallo oliver!

Ich verwende "pyodbc" für den Zugriff auf ODBC-Datenbanken.

Hier ein kleines Helferlein (für das Forum leicht verändert):

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
Datenbankzugriff per pyodbc

Requirements:  Python: http://www.python.org
               pyodbc: http://pyodbc.sourceforge.net/
"""

__all__ = ["MsSqlDB", "to_unicode", "to_dbstring"]

import pyodbc
import os
import sys

SQL_ENCODING = "iso-8859-1"


def to_unicode(text):
    """
    Wandelt den Datenbanktext nach Unicode um und normalisiert die
    Zeilenumbrüche.
    """
   
    if text is None:
        return None
   
    text = text.replace("\r\n", "\n")
   
    if isinstance(text, basestring):
        return text.decode(SQL_ENCODING)
    else:
        return text


def to_dbstring(text):
    """
    Wandelt Unicode in das SQL-Encoding um. Nebenbei werden Zeilenumbrüche
    in das Windows-Format umgewandelt.
    """

    if text is None:
        return None
   
    text = text.replace("\r\n", "\n")
    text = text.replace("\n", "\r\n")
   
    if isinstance(text, unicode):
        return text.encode(SQL_ENCODING)
    else:
        return text


class MsSqlDB(object):
    """
    Zugriff auf eine MS-SQLServer Datenbank
    """
   
    def __init__(self, username, password, database = "master", host = "(local)"):
        """
        Stellt die Verbindung zur Datenbank her.
        """
       
        # Verbinden
        connstr = """
        DRIVER=SQL Server;
        UID=%s;
        PWD=%s;
        DATABASE=%s;
        SERVER=%s;
        APP=Microsoft Data Access Components;
        """ % (
            username,
            password,
            database,
            host,
        )
        self.conn = pyodbc.connect(connstr)


def main():
    """
    Testen
    """
   
    db = MsSqlDB("username", "password", "dbname", "(local)")
    conn = db.conn
    cur = conn.cursor()
    
    sql = """
    SELECT TOP 100
        ArtikelNr as article_id,
        Bezeichnung as name
    FROM
        tArtikel
    """
    for row in cur.execute(sql):
        print row.article_id
        print repr(to_unicode(row.name))
        print
   
    cur.close()
    conn.close()


if __name__ == "__main__":
    main()
- http://pyodbc.sourceforge.net/
- http://www.connectionstrings.com/

mfg
Gerold
:-)

Edit: Um die Verwendung von __del__ nicht zu fördern, habe ich die __del__-Methode raus genommen.
Zuletzt geändert von gerold am Donnerstag 8. März 2007, 14:44, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Donnerstag 8. März 2007, 07:49

Hi Gerold,

Du lebst im Forum, oder! :-)

Der Tipp mit pyodbc ist klasse, danke.. !
Erscheint mir etwas "runder" als das bloße "odbc" Modul.

Mein (wirklich kleines) Problem mit dem
"select *" und den Feldnamen ist damit aber
wohl nicht gelöst, zumindest mit meinen Tests hier mit
pyodbc ist die Situation unverändert.. Wenn ich via "select *"
alle Felder abfrage, erhalte ich keinen zugriff auf die Feldnamen.
Das funktioniert nur, wenn ich wirklich explizit die gewünschten
Feldnamen im SQL-Statement angebe.

Ich hab extra nochmal nachgesehen.. In Java (mit jdbc) ging das,
zumindest laut meiner Doku hier (meine praktischen JDBC Erfahrungen
sind jetzt schon wieder etwas her, aus dem Stand kann ich mich
gerade nicht erinnern...). Wenn man dort aus einem ResultSet
etwas abgefragt hatte, konnte man auch immer über die Feldnamen
gehen, auch wenn die zugrunde liegende Abfrage mittels "*" lief.

pyodbc ist also vom Verhalten her ähnlich wie das Gespann
odbc + dtuple, der Fehler ist auch fast gleich..

(Z.b. hier mal der Zugriff auf ein Feld namens "Bez" nach einer Abfrage mit "*",
die for-loop und dergleichen spare ich mir jetzt.. "row" enthält halt die gerade aktuelle Zeile des Ergebnis-Sets)
-------
print row.bez
'pyodbc.Row' object has no attribute 'bez'

Das ganze funktioniert aber sofort wenn ich via "select bez from ..."
abfrage.

Nicht, dass das jetzt ein SO großes Problem wäre, aber es ist doch
interessant.... finde ich.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 8. März 2007, 09:41

oliver1974 hat geschrieben:Das ganze funktioniert aber sofort wenn ich via "select bez from ..."
Hallo oliver!

Das lässt für mich nur einen Schluss zu: Du bekommst von der Datenbank die Informationen über die Feldnamen nicht korrekt zurück. Da ich dieses Problem beim MS SQL-Server nicht habe, dürfte das ein Problem mit deinem Datenbanksystem (bzw. mit dem zugehörigen ODBC-Treiber) sein. In diesem Fall würde ich auf ``SELECT *`` komplett verzichten -- ist eh langsamer als die explizite Angabe der Feldnamen.

Was du so als Feldnamen zurück kriegst, bekommst du mit ``cur.description`` raus.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
oliver1974
User
Beiträge: 97
Registriert: Donnerstag 26. Oktober 2006, 15:01

Donnerstag 8. März 2007, 10:54

Hallo,

Das mit der inkorrekten Übergabe vom ODBC Treiber war inzwischen auch mein Gedanke... Aber nein, das Problem war ein ganz anderes.

Ich habe mir das description - Attribut des Cursors ausgeben lassen. Das war schön gefüllt, kein problem.

Aber: Die Feldnamen sind case-sensitive !!

Wenn ich sowas schreibe
"select bez from status"

ist der Feldname tatsächlich mittels
row.bez

zugreifbar.

Bei "select * from status"
aber sehe ich in der Description dass das Feld
korrekterweise "Bez" heisst...

"row.Bez"

liefert dann auch ganz brav den Inhalt.

Sorry, dass ich das nicht vorher bemerkt hatte.

Ist allerdings auch etwas verwirrend, dass das
implizit einfach umbenannt wird wenn man das
gewünschte Feld angibt. Schließlich
war das ja kein 'select Bez as "bez" ' oder so..
ich weiß gar nicht, ob das Verhalten standardkonform ist.

EDIT: Das DBMS ist wohl für die meisten etwas exotisch... Wenn wohl auch den Delphi - Programmierern gut bekannt, es handelt sich
um ADS (Advantage Database Server) von iAnywhere (vormals
Extended Systems)....

http://www.advantagedatabase.de/

Funktioniert sehr gut soweit, Treiber/Schnittstellen gibt es auch einige... Aber originale Python DB Treiber mal eben nicht so...
Zuletzt geändert von oliver1974 am Donnerstag 8. März 2007, 11:01, insgesamt 1-mal geändert.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Donnerstag 8. März 2007, 11:00

Hi Gerold.
Warum die Zeile:

Code: Alles auswählen

 text = text.replace("\r\n", "\n")
    text = text.replace("\n", "\r\n") 
Erst wandelst du alle \r\n in \n um und danach wider in \n :?

Dan eine kleine Kritik zu __del__:

Code: Alles auswählen

def __del__(self):
        """
        Datenbankverbindung schließen
        """
       
        self.conn.close() 
Damit wird nicht in jedenfall sichergestellt das die Connection tatsächlich geschlossen wird :-/ Sobald man es mit Zirkulären-Referenzen zu tun hat wird die Methode nie aufgeruffen.

Ich arbeite gerade an einer Applikation die ein von mir geschaffenes PI-System (Komponentesystem) benutzt, das per Metaklasse alle komponenten und deren Instanzen in einer Komponentenumgebung registiert, mit der es für Komponenteninstanzen möglich ist in allen Richtungen zu "Kommunizieren". Und genau da ist das Problem mit einer __del__-Methode, die niemals aufgeruffen wird, weil eine Zirkularität zwangsweise existiert :roll: [1]

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Foo(object):
    def __init__(self):
        self.bar = None
    
    def __del__(self):
        print "``__del__`` Methode von ``Foo`` aufgeruffen"

class Bar(object):
    def __init__(self, foo):
        self.foo = foo
    
    def __del__(self):
        print "``__del__`` Methode von ``Bar`` aufgeruffen"

    
foo = Foo()
bar = Bar(foo)

# Beim Scriptende wird "``__del__`` Methode von ``Foo`` aufgeruffen``" und "``__del__`` Methode von ``Bar`` aufgeruffen"
# ausgegeben.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Foo(object):
    def __init__(self):
        self.bar = None
    
    def __del__(self):
        print "``__del__`` Methode von ``Foo`` aufgeruffen"

class Bar(object):
    def __init__(self, foo):
        self.foo = foo
    
    def __del__(self):
        print "``__del__`` Methode von ``Bar`` aufgeruffen"
    
foo = Foo()
bar = Bar(foo)

foo.bar = bar

# Beim Scriptende wird nichts ausgegeben -> Zirkulare Referenz
Ok, ein stranges Beispiel und mag in der Praxis kaum vorkommen. Aber in einem PI-System das in beide Richtungen Kommunizieren kann, tritt sowas auf, sobald PIs eine Referenz einer Umgebung in sich beinhalten. In dem Fall tritt Zirkularität auf ob man will oder nicht.

[1]
Fall 1: Angenommen in der Umgebung existiert die Instanz von Komponente X und Komponenten X referenziert in sich die Umgebung. Daraus folgt das die Instanz über die Umgebung zusätzlich auf sich selbst zugreifen kann.
Fall 2: Angenommen in der Umgebung existieren eine Instanz von X und Y und es referenzieren sich beide Instanzen, zwecks Kommunikation. Selbst wenn beide Instanzen nur die Umgebung referenzieren würden, würden sich alle instanzen indirekt irgendwie auch referenzieren, da sie ja über die Umgebung auf sich und den Reste Zugriff haben :-[ -- Aber wie soll man sonst ein PlugIn-System schreiben bei dem alle PlugIns in alle Richtungen mit einander kommunizieren können.


Worauf ich nun hinaus will ist, das ich dem Destruktor einer Klasse kein stück mehr über den Weg traue und schon garnicht nach dieser Beschreibung: http://docs.python.org/ref/customization.html

Gerold, ich würde lieber explizit eine Methode schreiben mit der man die Connection der DB schließen kann, auch wenn in der Praxis eine Zrikularität zu 80%(?) nicht zu stande kommt.


BTW: Sorry für das "OT".

lg
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 8. März 2007, 12:48

sape hat geschrieben:Warum die Zeile:

Code: Alles auswählen

 text = text.replace("\r\n", "\n")
    text = text.replace("\n", "\r\n") 
Erst wandelst du alle \r\n in \n um und danach wider in \n :?
Dan eine kleine Kritik zu __del__
Hi sape!

Zu Punkt 1:
Was ist, wenn in dem Text gemischte Zeilenumbrüche drinnen sind? Probier es selber aus: "a\nb\r\nc\r\nd"
Ohne die erste Zeile würde ich das raus kriegen: "a\r\nb\r\r\nc\r\r\nd" Und das ist nicht das, was ich haben möchte.

Zu Punkt 2:
Ich weiß dass __del__ nicht immer aufgerufen wird. Ich weiß aber auch, dass die Connection sich selber schließt, wenn diese vom GC gelöscht wird. Die Connection im __del__ zu schließen ist nur ZUSÄTZLICH, falls ich es vergesse, explizit zu machen. Es stört den Programmablauf nicht und kann nicht schaden.

In den meisten Fällen läuft es genau so, wie ich es möchte. Und wenn __del__ nicht aufgerufen wird, stört es mich nicht im geringsten. :D Und wenn es aufgerufen wird, dann um so besser.

Viele wettern (warum auch immer) so gegen __del__. Ich verstehe es nicht, denn in __del__ werde ich nie kritischen Code rein schreiben. Wenn etwas so wichtig ist, dass es unbedingt erledigt werden muss, dann schreibe ich eine eigene Methode dafür. Wenn etwas nicht wichtig ist, ich es aber gerne sehe, wenn es automatisch erledigt wird, dann schreibe ich es in die __del__-Methode. So einfach ist das.

In meinem Beispiel ist ``self.conn`` eine direkte Referenz zur Connection. Wenn ich die Connection also im Code explizit schließen möchte, dann genügt ein ``xxx.conn.close()``. -- Was ich normalerweise auch mache.

lg
Gerold
:-)

PS: Der MSSQL-Server gibt leider kein "\n" als Zeilenumbruch zurück, deshalb muss ich mich selber darum kümmern. Leider wandelt die ODBC-Schnittstelle die "\n" nicht automatisch in "\r\n" um, was aber unbedingt sein muss, damit andere Anwendungen, die auf die gleichen Daten zugreifen, noch korrekt funktionieren.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BlackJack

Donnerstag 8. März 2007, 14:11

Ich bin auch einer von denen die gegen `__del__()` wettern. Du schreibst selbst, dass es nichts bringt, handelst Dir also nur die Nachteile ein. Zum Beispiel, dass die Objekte dann vom Garbage-Collector ausgenommen werden. Und allgemein muss man höllisch aufpassen was man in der Methode benutzt. Alles was nicht an die Instanz gebunden ist, kann zum Zeitpunkt des Aufrufs schon weg sein. Also nicht einmal ein einfaches ``print`` funktioniert garantiert.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 8. März 2007, 14:40

BlackJack hat geschrieben:Zum Beispiel, dass die Objekte dann vom Garbage-Collector ausgenommen werden. Und allgemein muss man höllisch aufpassen was man in der Methode benutzt. Alles was nicht an die Instanz gebunden ist, kann zum Zeitpunkt des Aufrufs schon weg sein. Also nicht einmal ein einfaches ``print`` funktioniert garantiert.
Hi BlackJack! Hi all!

Ich glaube, du malst den Teufel an die Wand!
Aber mit einem hast du recht. Wenn man nicht weiß, was man sich einhandelt, dann wird man ziemlich überrascht sein, wenn etwas nicht mehr so wie gewünscht funktioniert. Und da ich glaube, dass nicht jeder hier die Hilfe zu __del__ durchgelesen und verstanden hat und die Auswirkungen evt. auch nicht abschätzten kann, werde ich bei Code, den ich hier ins Forum stelle, versuchen, __del__-Methoden raus zu nehmen.

Das einfache Definieren der Methode __del__ nimmt die Klasseninstanz nicht vom GC aus. Wie kommst du darauf? Es braucht schon besondere Umstände dafür. Oder was weiß ich darüber noch nicht?

``print`` innherhalb der __del__-Methode funktioniert immer. Man sollte aber nichts an ``print`` übergeben, was nicht mehr existiert...

Also Leute! Wenn ihr __del__ verwendet und von dieser Klasse ableitet, und in der abgeleiteten Klasse __del__ überschreibt, dann achtet darauf, __del__ der Superklasse explizit aufzurufen... Handelt euch keine zirkulären Referenzen ein und verursacht keine Fehler in der Klasseninstanz, so dass keine Referenzen zur Instanz über das Traceback übrig bleiben.

Ach ja! Verwendet __del__ nicht in Threads, die sich sehr oft neu starten. Wenn in diesem Fall ein Fehler innerhalb des Threads auftritt, dann wird das Objekt nicht vom GC entsorgt. Was bei vielen Threads zu Speicherproblemen führen kann.

Verwendet __del__ nicht und zerstört eure Objekte explizit und lasst mich __del__ verwenden wenn ich will. :twisted:

Habe ich etwas vergessen? ;-)

lg
Gerold
:-)

PS: Ich bin __del__-Vielverbraucher. Ich habe __del__ schon mindestens zehn mal in meinem Leben verwendet. :mrgreen:
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Donnerstag 8. März 2007, 14:58

gerold hat geschrieben: Ich weiß dass __del__ nicht immer aufgerufen wird. Ich weiß aber auch, dass die Connection sich selber schließt, wenn diese vom GC gelöscht wird.
Nein, das passiert eben nicht. Die Connection wird bei der Terminierung des Programmes geschlossen, in der auch registrierte Speicher vom OS freigegeben wird.

Aber in dem Fall von dir, wird es kaum in einer Datenstruktur verwendet werden, in denen zirkularität vor kommen können. Es könnte aber der Fall sein. Und da möchte der Benutzer mehrer verschiedene DBs ansprechen und auch welche schließen. Dan haben wir das Problem, das wir auf einmal ein stetig ansteigenden Speicher haben -- Speicherlecks.
Genau das macht für mich den "Destuktor" von Klassen in Python unsympathisch, da er sich, wegen einen primitiven GCs (Der nur auf einer Referenzzählung basiert), nicht wie ein "echter" Destruktor verhält, wie z.B. in C++.
gerold hat geschrieben: Die Connection im __del__ zu schließen ist nur ZUSÄTZLICH, falls ich es vergesse, explizit zu machen. Es stört den Programmablauf nicht und kann nicht schaden.
Naja, aber wenn das System ansich fehleranfällig ist, wie soll es dich "schützen" und was soll es bringen in Fall das du vergisst die Connection zu schließen?
gerold hat geschrieben: In den meisten Fällen läuft es genau so, wie ich es möchte. Und wenn __del__ nicht aufgerufen wird, stört es mich nicht im geringsten. :D Und wenn es aufgerufen wird, dann um so besser.
Und genau die Begründung macht es dann überflüssig. Wenn ich eine Funktionalität nicht brauche oder mir egal ist ob sie implizit ausgeführt wird oder nciht, dann braucht man das auch nicht zu implementieren.
gerold hat geschrieben: Viele wettern (warum auch immer) so gegen __del__. Ich verstehe es nicht, denn in __del__ werde ich nie kritischen Code rein schreiben.
Ja, und das mit guten recht. Der GC von Python ist, käse ;) Er basiert nur auf eine Referenzzählung das die primitivste Implementierung eines GCs ist. Das Problem ist, das so eine Implementierung nicht im strande ist, zirkuläre Referenzen zu durchbrechen, da ja ein Objekt erst vom GC gelöscht wird wenn der Counter auf 0 ist. Wenn sich aber zwei Objekte gegenseitig referenzieren kann der Counter nie auf 0 kommen. Somit wird so ein Objekt nie freigegeben, wenn kein Name mehr auf ein Objekt zeigt. Und da kommen wir auch zum Destruktor der eigentlich überflüssig wird, da er sich nicht wie ein richtige verhält :-/ Den Python sagt, ein Desktruktor wird erst dann aufgeruffen wenn die letzte Referenz zum Objekt gelöscht ist (Was ja auch logisch ist).


gerold hat geschrieben: Wenn etwas so wichtig ist, dass es unbedingt erledigt werden muss, dann schreibe ich eine eigene Methode dafür. Wenn etwas nicht wichtig ist, ich es aber gerne sehe, wenn es automatisch erledigt wird, dann schreibe ich es in die __del__-Methode. So einfach ist das.
Warum etwas erledigen lassen was ohne belangen ist? Und, eigentlich ist es die Aufgabe eines Desktruktor, wichtige aufräum arbeiten einer Instanz von Klasse X erledigen zu lasen (So kenne ich das von C++). Da es aber nicht gewährleistet wird, macht es den Klassen-"Destruktor" in Python überflüssig.

Ich wünsche mir für Py3k einen vernümftigen GC, damit ich mir keine Gedanken über sowas lästigen machen muss, weswegen ich heute nicht mehr mit C/C++ Programmieren möchte. Im Fall meiner Applikation (Die zu Speicherlecks, wegen dem besagten tendiert), muss ich mir nun irgendwann, wenn es die Zeit zulässt (Das hat die niedrigste Priorität auf meiner TODO-List), Gedanken machen wie ich das Problem löse...
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Donnerstag 8. März 2007, 15:14

gerold hat geschrieben: Ich glaube, du malst den Teufel an die Wand!
Nein das denke ich nicht, da es meine 2 wöchige Erfahrung mit der Thematik auch widerspiegelt.
gerold hat geschrieben: Das einfache Definieren der Methode __del__ nimmt die Klasseninstanz nicht vom GC aus. Wie kommst du darauf? Es braucht schon besondere Umstände dafür. Oder was weiß ich darüber noch nicht?
Sieh dir mein zweites Beispiel da oben an. Da wird eine Zirkularität zwischen ``foo`` und ``bar`` erzeugt und ab dem Zeitpunkt wird bei einem ``del foo, bar`` die Destruktoren der Klassen nie aufgerufen werden (Wie gesagt wird der Destruktor nur aufgeruffen, wenn der Referenzzähler eines Objektes auf 0 steht, das bei Selbstreferenz oder Zirkularer Referenz nie erreicht wird.). Auch werden die nicht mehr erreichbaren Objekte vom GC nicht speicherbereinigt!
gerold hat geschrieben: ``print`` innherhalb der __del__-Methode funktioniert immer. Man sollte aber nichts an ``print`` übergeben, was nicht mehr existiert...
Nein, nicht immer.
gerold hat geschrieben:Handelt euch keine zirkulären Referenzen ein
Leichter gesagt als getan. Ein AST z.B. basiert ja auch irgendwie auf Zirkularität. Ein PlugIn-System das es den PlugIns erlaubt in beiden Seiten zu Kommunizieren, das es erlaubt von Beiden Seiten "Ein Gespräch Anzufangen", kann nur durch sowas realisiert werden. Eine andere Möglichkeit ist mir nicht bekannt.

gerold hat geschrieben: Verwendet __del__ nicht und zerstört eure Objekte explizit und lasst mich __del__ verwenden wenn ich will. :twisted:

Habe ich etwas vergessen? ;-)
Gerold, das ist nicht vom mir böse gemeint gewesen ;) Ich wollte nur mal auf die Gefahren hinweisen. Wenn ich das alles vorher gewusste hätte, hätte ich mir 4 Tage Stress erspart mit meinem PlugIn-System :-[ Daher wollte ich nur darauf hinweise, den man weiß nie, wann es doch mal anders kommt als gedacht und dann ist wohl alles vom ``__del__`` abhängig das nicht wie erwartet arbeitet ;)

Naja, nochmals sorry für den OT. Vielleicht kann man die Diskussion in einem anderen Thread verlagern.

lg
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 8. März 2007, 15:27

sape hat geschrieben:Gerold, das ist nicht vom mir böse gemeint gewesen ;)
Hi sape! Hi BlackJack!

Es könnte ja sein, dass ihr -- BlackJack und du -- evt. ansatzweise recht habt, aber das würde ich niemals offen zugeben. :wink:

lg
Gerold
:mrgreen: :mrgreen:
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
BlackJack

Donnerstag 8. März 2007, 16:07

gerold hat geschrieben:Das einfache Definieren der Methode __del__ nimmt die Klasseninstanz nicht vom GC aus. Wie kommst du darauf?
Okay, ich habe die Referenzzählung nicht zum GC gezählt, sondern nur den "richtigen" GC gemeint, also der den man auch abstellen kann. Der fasst Objekte mit `__del__()`-Methode nicht mehr an.
``print`` innherhalb der __del__-Methode funktioniert immer. Man sollte aber nichts an ``print`` übergeben, was nicht mehr existiert...
Und was passiert wenn die `__del__()`-Methode aufgerufen wird wenn beim beenden eines Programms `sys.stdout` schon "entsorgt" wurde? Ich würde mich nicht darauf verlassen dass das noch da ist.
Antworten