Seite 1 von 1

PyGTK und psycopg2

Verfasst: Mittwoch 7. Dezember 2011, 16:30
von truehumandesign
Hi!

Ich habe folgende Frage:
Ich möchte per Button eine Verbindung zum PostgreSQL Server herstellen und diese soll bestehen bleiben, bis der Disconnect Button aktiviert wird.
Mein Programm sieht zur Zeit folgendermaßen aus:

Code: Alles auswählen

import pygtk
pygtk.require("2.0")
import gtk
import psycopg2

class portOpt(object):    
	def __init__(self):
	    self.builder = gtk.Builder()
	    self.builder.add_from_file("portoptv3.glade")
	    self.builder.connect_signals(self)
	    self.window = self.builder.get_object("window1")
	    self.window.show()
	    
	def execute(self, *args):
		host = self.builder.get_object('host').get_text()
		db = self.builder.get_object('db').get_text()
		user = self.builder.get_object('user').get_text()
		pw = self.builder.get_object('pw').get_text()
		conn_string = "host="+ host +" dbname="+ db +" user="+ user +" password="+ pw +""
		conn = psycopg2.connect(conn_string)
		cur = conn.cursor
				
	def on_bt_quit_activate(self,widget, data=None):
		gtk.main_quit()
		
	def on_window1_destroy(self,widget, data=None):
		gtk.main_quit()
		
	def on_act_con_activate(self, *args):
		self.execute()
		
	def on_act_discon_activate(self, *args):
		cur.close()
		conn.close()
				
if __name__ == "__main__":
	app = portOpt()
	gtk.main()
Das Connecten an sich funktioniert, jedoch bleibt die Verbindung nicht aufrecht erhalten.
Dazu kommt noch, dass ich keine Ahnung habe wie ich die "conn" und "cur" auf die act_discon übergeben kann.
Diese Aktion soll ja den Cursor nach beendigung der Aktionen (Die im Moment noch nicht enthalten sind) schließen und dann die Datenbankverbindung trennen.

Dank und Gruß...

Re: PyGTK und psycopg2

Verfasst: Mittwoch 7. Dezember 2011, 17:09
von Hyperion
Naja, Du müßtest einfach die Connection in einem Attribut Deines Objektes hinterlegen :K

Ich würde die Methode zum Verbindungsaufbau auch nicht ``execute`` nennen - so heißt ja beim DB-API2 die Methode zum Absetzen eines SQL-Kommandos. Das ist imho verwirrend.

Klassennamen schreibt man "CamelCase" nach PEP8 - oder ist das bei GtK ggf. eine Ausnahme und bewusst so gehalten?

Re: PyGTK und psycopg2

Verfasst: Mittwoch 7. Dezember 2011, 17:21
von truehumandesign
Hyperion hat geschrieben:Naja, Du müßtest einfach die Connection in einem Attribut Deines Objektes hinterlegen :K

Ich würde die Methode zum Verbindungsaufbau auch nicht ``execute`` nennen - so heißt ja beim DB-API2 die Methode zum Absetzen eines SQL-Kommandos. Das ist imho verwirrend.

Klassennamen schreibt man "CamelCase" nach PEP8 - oder ist das bei GtK ggf. eine Ausnahme und bewusst so gehalten?
Das execute war nur testweise und ändert sich definitiv wenns mal funktioniert :)

Ok zu deiner Antwort.
Ich will ja mit dem einen Object die Verbindung herstellen und halten
und mit dem anderen die Verbindung trennen.
da ''conn'' aber nicht global festgelegt sonder nur im "Verbindung herstellen" object übernimmt er das nicht in das "Verbindung trennen" object.

Re: PyGTK und psycopg2

Verfasst: Mittwoch 7. Dezember 2011, 17:26
von Hyperion
truehumandesign hat geschrieben: da ''conn'' aber nicht global festgelegt sonder nur im "Verbindung herstellen" object übernimmt er das nicht in das "Verbindung trennen" object.
Äh... was sollen das für Objekte sein? Redest Du von den Methoden der Klasse ``portOpt``? Diese haben aber keine "Attribute", sondern kennen nur Namen, die entweder lokal definiert sind - so wie momentan ``conn`` - oder aber das jeweilige "Instanz"-Objekt, welches sie über ``self`` bekommen.

Du musst die Verbindung innerhalb einer Instanz von ``portOpt`` hinterlegen - oder aber direkt als Klassenattribut. Auf jeden Fall muss das ganze "global" innerhalb Deiner Klasse verfügbar sein - ansonsten kannst Du die Klasse auch weglassen und die DB-Verbindung extern verwalten...

Re: PyGTK und psycopg2

Verfasst: Mittwoch 7. Dezember 2011, 17:50
von deets
Ich sehe hier vor allem die Gefahr einer wirklich unheiligen Vermischung aus GUI-Code & Anwendungs-Schicht.

Du koenntest dem Problem zum Beispiel dadurch begegnen, indem du ein Application-Objekt oder etwas aenhliches erstellst, das einem Singleton oder Borg-Pattern folgt.

Damit kannst du dann in deine GUI-Callbacks sage "Application().setup_connection()" oder so.

In dem Application-Objekt solltest du natuerlich auch eine eventuelle Konfiguration speichern, und wenn die via GUI neu definiert wird, dann darin erstmal setzen. Oder "Application().setup_connection(db_uri)" machen.

Und zum zusammenbau von Strings benutze doch bitte string-formatierung, und nicht den +-Operator... (Ja, problembaer, der ist auch nicht verboten vom Interpreter, aber trotzdem schlecht...)

Re: PyGTK und psycopg2

Verfasst: Mittwoch 7. Dezember 2011, 18:47
von truehumandesign
Hyperion hat geschrieben:
truehumandesign hat geschrieben: da ''conn'' aber nicht global festgelegt sonder nur im "Verbindung herstellen" object übernimmt er das nicht in das "Verbindung trennen" object.
Äh... was sollen das für Objekte sein? Redest Du von den Methoden der Klasse ``portOpt``? Diese haben aber keine "Attribute", sondern kennen nur Namen, die entweder lokal definiert sind - so wie momentan ``conn`` - oder aber das jeweilige "Instanz"-Objekt, welches sie über ``self`` bekommen.

Du musst die Verbindung innerhalb einer Instanz von ``portOpt`` hinterlegen - oder aber direkt als Klassenattribut. Auf jeden Fall muss das ganze "global" innerhalb Deiner Klasse verfügbar sein - ansonsten kannst Du die Klasse auch weglassen und die DB-Verbindung extern verwalten...
Sorry ich bin ein absoluter python noob hab mich falsch ausgedrückt.. natürlich meinte ich nicht Objekte sondern die Methoden der Klasse portOpt.
Ich mach mich morgen nochmal an das ganze und melde mich ob ichs hinbekommen habe.

Danke mal soweit!

Re: PyGTK und psycopg2

Verfasst: Donnerstag 8. Dezember 2011, 08:54
von truehumandesign
Soo.. ich hab mir mal das Python Tutorial zu den Klassen zu gemüte geführt.

Der Code sieht nun folgendermaßen aus:

Code: Alles auswählen

import pygtk
pygtk.require("2.0")
import gtk
import psycopg2

class portOptPrg(object):
	
	def con_db(self, *args):
		host = self.builder.get_object('host').get_text()
		db = self.builder.get_object('db').get_text()
		user = self.builder.get_object('user').get_text()
		pw = self.builder.get_object('pw').get_text()
		conn_string = "host=self.host dbname=self.db user=self.user password=self.pw"
		conn = psycopg2.connect(conn_string)

	def con_disc(self, *args):
		conn.close()

class portOptGui(portOptPrg):    
	def __init__(self):
	    self.builder = gtk.Builder()
	    self.builder.add_from_file("portoptv3.glade")
	    self.builder.connect_signals(self)
	    self.window = self.builder.get_object("window1")
	    self.window.show()
				
	def on_bt_quit_activate(self,widget, data=None):
		gtk.main_quit()
		
	def on_window1_destroy(self,widget, data=None):
		gtk.main_quit()
		
	def on_act_con_activate(self, *args):
		self.con_db()
		
	def on_act_discon_activate(self, *args):
		self.con_disc()
				
if __name__ == "__main__":
	app = portOptGui()
	gtk.main()

Jetzt steh ich nur wieder vor dem gleichen Problem und ich bekomm die Verbindung nicht geschlossen.
Ich hab schon in der psycopg2 doc geschaut ob es ein disconnect befehl oder ähnliches gibt.. finde aber nichts dazu.
Ich bekomm den Parameter "conn" einfach nicht übergeben
Python bringt mir folgenden fehler:
Traceback (most recent call last):
File "portoopv4.py", line 37, in on_act_discon_activate
self.con_disc()
File "portoopv4.py", line 17, in con_disc
conn.close()
NameError: global name 'conn' is not defined
Wo hakts hier noch?

Re: PyGTK und psycopg2

Verfasst: Donnerstag 8. Dezember 2011, 10:56
von deets
Oh mann... das ist wirklich gruselig.

Zuerstmal hakt es immer noch, weil du deine conn nirgendwo speicherst. Du musst

Code: Alles auswählen

      self.conn = psycopg2.connect(conn_string)
machen, und natuerlich auch in disconnect dich auf self.conn beziehen.

Und dann mal ein paar Anmerkungen:

Die Zerteilung in zwei Klassen hat das ganze deutlich verschlimmert. Denn du erstellst eine Basisklasse, die jede Menge Detailwissen vorraussetzt ueber eine Klasse, die von ihr ableitet. Das ist ganz schlechtes Design. Denn wer sagt denn, dass du nicht auch eine GUI programmieren willst, die den connection string als ganzes, inklusive username/passwort usw entgegennimmt - also nur *ein* Texteingabefeld hat? Das wuerde mit deinem jetztigen Ansatz nicht funktionieren.

Also, portOptPrg bekommt den conn_string als Argument an con_db, und das war's.

Und portOptGui erbt nicht von portOptPrg, sondern bekommt eine Instanz davon bei Konstruktion, oder es gibt davon eine globale Variable.

Dann ist deine Namenskonvention ungewoehnlich - Klassen haben CamelCase. Und die ganzen Abkuerzungen sind verwirrend. Warum heissen con_db und con_disc nicht einfach connect_db & disconnect_db?

Last but not least - wenn das, was du hier postest, wirklich dein echter Code ist, dann ist der conn_string voellig sinnfrei zusammengebaut. So funktioniert string-formatting nicht (falls es das sein sollte).

Re: PyGTK und psycopg2

Verfasst: Donnerstag 8. Dezember 2011, 14:03
von truehumandesign
deets hat geschrieben:Oh mann... das ist wirklich gruselig.

Zuerstmal hakt es immer noch, weil du deine conn nirgendwo speicherst. Du musst

Code: Alles auswählen

      self.conn = psycopg2.connect(conn_string)
machen, und natuerlich auch in disconnect dich auf self.conn beziehen.

Und dann mal ein paar Anmerkungen:

Die Zerteilung in zwei Klassen hat das ganze deutlich verschlimmert. Denn du erstellst eine Basisklasse, die jede Menge Detailwissen vorraussetzt ueber eine Klasse, die von ihr ableitet. Das ist ganz schlechtes Design. Denn wer sagt denn, dass du nicht auch eine GUI programmieren willst, die den connection string als ganzes, inklusive username/passwort usw entgegennimmt - also nur *ein* Texteingabefeld hat? Das wuerde mit deinem jetztigen Ansatz nicht funktionieren.

Also, portOptPrg bekommt den conn_string als Argument an con_db, und das war's.

Und portOptGui erbt nicht von portOptPrg, sondern bekommt eine Instanz davon bei Konstruktion, oder es gibt davon eine globale Variable.

Dann ist deine Namenskonvention ungewoehnlich - Klassen haben CamelCase. Und die ganzen Abkuerzungen sind verwirrend. Warum heissen con_db und con_disc nicht einfach connect_db & disconnect_db?

Last but not least - wenn das, was du hier postest, wirklich dein echter Code ist, dann ist der conn_string voellig sinnfrei zusammengebaut. So funktioniert string-formatting nicht (falls es das sein sollte).
Ich nehme gerne Tipps entgegen, jedoch könntest du vllt. mal auf meine vorherigen Posts achten und du wirst erkennen, dass ich geschrieben habe:
Sorry ich bin ein absoluter python noob
Also kannst du mir das bitte auch normal erklären und nicht (für mich redest du teilweise in rätseln) mit deiner Formatierungsvorgabe kommen und lieber mal auf eine Seite verweisen die diese ganzen Standards vorweist die du mir da aufzählst.
Schreib doch zum Beispiel lieber mal was "Sinnfrei" am con_string ist, dann lern ich auch was dabei.
Oder einfach mal den Gesamten Code, so wie du es meinst.. (wenns nicht zu viel verlangt ist).
Ein Freundlicher Umgangston scheint aber unter Codern (mit n00bs) eh nicht gang und gebe zu sein (den Eindruck habe ich zumindest)

Danke..

Re: PyGTK und psycopg2

Verfasst: Donnerstag 8. Dezember 2011, 14:17
von deets
@ truehumandesign

"sinnfrei" ist es, weil du schreibst

"host=self.host dbname=self.db user=self.user password=self.pw"

Das heisst einen String, der *genau* so aussieht. Was du aber offensichtlich wolltest ist, den connection-string basierend auf den ganzen parametern aufzubauen.

Also etwa so:

conn_string = "host='%s' dbname='%s'" % (host, dbname)

Natuerlich mit all den anderen parametern genauso.

Da dein Code da oben eh nie einen vernuenftigen conn-string hat zusammenbauen koennen, stellt sich natuerlich die Frage, wie du ueberhaupt jemals eine Datenbankverbindung aufgebaut hast, die du dann ueberhaupt disconnecten willst. Oder sollte es sich etwa gar nicht um den richtige Code handeln??? Dann ist das hier ja sowieso trocken-schwimmen...

Und was das Noob-Sein angeht: wenn du das Tutorial durchgearbeitet hast, und in der Lage bist, fuer sowas wie self.builder die richtige Herangehensweiseise zu waehlen, aber nicht bei "self.conn", dann kann ich da nur drauf hinweisen - aber dich da abzuholen bei Pontius & Pilatus scheint mir nicht noetig. Und wenn du Begriffe genannt bekommst, die du nicht kennst - wie zB string-formatting - dann kann man die auch googeln.

Re: PyGTK und psycopg2

Verfasst: Donnerstag 8. Dezember 2011, 15:01
von truehumandesign
OK vielen Dank für die Tipps erstmal.
Hat mich doch schon weiter gebracht mittlerweile.
Mir fehlte der Zusammenhang, dass ein self. vor dem parameter diesen global ablegt und über self. dann wieder aufgerufen werden kann.
Das Programm soll keineswegs produktiv eingesetzt werden, sondern ist einfach nur ein Test bzw. eine Spielerei mit pygtk, und deshalb geh ich da jetzt nicht strikt nach Formatierungsvorgaben vor.
Wie dem auch sei.. die Verbindung kann nun getrennt werden und das ist es ja was ich wollte.

Re: PyGTK und psycopg2

Verfasst: Donnerstag 8. Dezember 2011, 15:36
von deets
@truehumandesign

Du hast da etwas sehr grundlegendes nicht verstanden: self.foo legt etwas *NICHT* global ab, sondern als Attribut einer Instanz deines Objektes:

Code: Alles auswählen


class Foo(object):

    def __init__(self, arg):
         self.arg = arg

a = Foo(10)
b = Foo(20)
assert a.arg != b.arg
Global geht auch (mit "global"), aber das sollte man wenn irgend moeglich immer vermeiden. Dazu findest du hier genug Diskussionen.

Und das Argument "ist nur zum ausprobieren" ist immer schwierig... nichts haelt so lang, wie ein Provisorium. Auch und gerade wenn es um's lernen geht, solltes du dich um vernuenftiges programmieren bemuehen. Wann sonst lernst du es - wenn die Zeit im Projekt draengt eher nicht...

Re: PyGTK und psycopg2

Verfasst: Donnerstag 8. Dezember 2011, 15:52
von truehumandesign
deets hat geschrieben: Und das Argument "ist nur zum ausprobieren" ist immer schwierig... nichts haelt so lang, wie ein Provisorium. Auch und gerade wenn es um's lernen geht, solltes du dich um vernuenftiges programmieren bemuehen. Wann sonst lernst du es - wenn die Zeit im Projekt draengt eher nicht...
Wahre worte!

Danke für den Support!

Re: PyGTK und psycopg2

Verfasst: Samstag 10. Dezember 2011, 12:32
von truehumandesign
Hi!

Ich habe schon wieder eine Frage:
Undzwar möchte ich eine Datenbankabfrage gerne in einem TextView darstellen.
Jedoch geht das wohl nicht, weil die Formatierung des "fetch" von psycopg irgendwas verhaut (oder ich selbst :) )
Meine Funktion sieht folgendermaßen aus:

Code: Alles auswählen

def selectall(self, *args):
		cur = self.conn.cursor()
		cur.execute('SELECT * FROM foo')
		text = cur.fetchone()
		buffer = self.builder.get_object('view_log').get_buffer()
		buffer.set_text("%s") % text
		self.conn.commit()
		cur.close()
Wenn ich das Ganze als "print" ausgebe kommt das hier raus:
(1, 'ZL0000001', 'Klemmerle', 'Bushaltestelle 1', '12345', '99999')
Vielleicht hat mir irgendjemand einen Tipp hierfür
Danke!

Re: PyGTK und psycopg2

Verfasst: Samstag 10. Dezember 2011, 12:43
von BlackJack
@truehumandesign: Schau Dir mal in der Dokumentation oder auch live (`type()`-Funktion) bei dem Objekt was Du von `fetchone()` bekommst, wie das aufgebaut ist.

Re: PyGTK und psycopg2

Verfasst: Samstag 10. Dezember 2011, 15:31
von truehumandesign
Er spuckt mir folgendes aus:
<type 'tuple'>
Traceback (most recent call last):
File "portoopv5.py", line 63, in on_act_select_activate
self.selectall()
File "portoopv5.py", line 33, in selectall
buffer.set_text("%s") % text
TypeError: unsupported operand type(s) for %: 'NoneType' and 'tuple'
Ich google mal gerade zu tuples und textbuffer

Edit: so bekomm ich zumindest die Abfrage raus (nur nicht richtig formatiert) type müsste eigentlich unicode sein, da der Zeichensatz von Pgsql auf UTF-8 gestellt ist.
Und normalerweise sollte buffer.set_text(text) schon unicode sein.

Code: Alles auswählen

buffer.set_text(repr(text))
(1, u'ZL0000001', u'Klemmerle', u'Bushaltestelle 1', u'12345', u'99999')

so sieht die Ausgabe im textview aus

Re: PyGTK und psycopg2

Verfasst: Samstag 10. Dezember 2011, 16:00
von BlackJack
@truehumandesign: Wenn Du `tuple` nicht kennst, dann solltest Du jetzt Datenbank und GUI mal solange beiseite lassen bis Du die Python-Grundlagen drauf hast. Arbeite am besten mal das Tutorial aus der Python-Dokumentation durch.

Und in der Zeile ist noch ein anderes Problem gewesen: Schau mal was links vom ``%``-Operator steht.

Re: PyGTK und psycopg2

Verfasst: Samstag 10. Dezember 2011, 16:06
von truehumandesign
BlackJack hat geschrieben:@truehumandesign: Wenn Du `tuple` nicht kennst, dann solltest Du jetzt Datenbank und GUI mal solange beiseite lassen bis Du die Python-Grundlagen drauf hast. Arbeite am besten mal das Tutorial aus der Python-Dokumentation durch.

Und in der Zeile ist noch ein anderes Problem gewesen: Schau mal was links vom ``%``-Operator steht.
Meinst du buffer.set_text?
Wegen der bezeichnung text?

Edit:

Na alla,
def selectall(self, *args):
cur = self.conn.cursor()
cur.execute('SELECT * FROM foo')
outp = cur.fetchone()
buffer = self.builder.get_object('view_log').get_buffer()
buffer.set_text(outp[2])
self.conn.commit()
cur.close()
So gehts!

Re: PyGTK und psycopg2

Verfasst: Samstag 10. Dezember 2011, 17:57
von BlackJack
@truehumandesign: Ich meinte keine Bezeichnung sondern den Typ der letztendlich links vom ``%``-Operator gestanden hat. Die Methode gibt `None` zurück, darauf kann man sowieso kein ``%`` anwenden, was die Ausnahme ja auch sehr deutlich aussagt.

Re: PyGTK und psycopg2

Verfasst: Samstag 10. Dezember 2011, 19:53
von truehumandesign
Ich arbeite jetzt erstmal diverse tutorials durch bevor ich mich gleich mit so Sachen beschäftige, wird wohl besser sein. Ich weiss zum Beispiel jetzt nicht warum der None zurück gibt.
Kann mir jemand noch ein paar tutorials die nicht Auf der offiziellen Python Seite vorhanden sind empfehlen?
Danke!