Da Du immer gesagt hast beim Client käme der Fehler, habe ich an die Möglichkeit auch nicht gedacht.
Hast Du beide Programme in der gleichen Konsole gestartet? Wenn man beide in unterschiedlichen startet, sieht man schneller wer da mit Ausnahmen um sich wirft.
Keyserver - Dateienaustausch und Abruf
Nee, ich hatte es schon in 2 verschiedenen Consolen laufen. Es war übrigens genau der gleiche Fehler den ich vorher auch schonmal hatte Jetzt aber zu einem weiteren Problem.
Es funktionieren soweit alle Methoden, keys speichern einen abrufen, suchen nach versch. Kriterien, keine doppelte Speicherung usw.
Das einzige was ich nicht so ganz hinbekomme, ist die Funktion listAllKeys(), wie der Name schon sagt, möchte ich alle Keys auslesen und an den Client senden:
Implementation:
server.py
client.py
er gibt mir aber nur den ersten key in der liste aus. Man könnte ja erst alle in eine Datei schreiben und dann übergeben, find ich aber nicht so elegant.
Hat da jemand vielleicht noch eine andere Idee??
Danke und Gruß
Christian
Es funktionieren soweit alle Methoden, keys speichern einen abrufen, suchen nach versch. Kriterien, keine doppelte Speicherung usw.
Das einzige was ich nicht so ganz hinbekomme, ist die Funktion listAllKeys(), wie der Name schon sagt, möchte ich alle Keys auslesen und an den Client senden:
Implementation:
server.py
Code: Alles auswählen
def listAllKeys(self):
for key in keys.itervalues():
return key.algo, key.key, key.hashval, key.name, key.host
Code: Alles auswählen
print server.listAllKeys()
Hat da jemand vielleicht noch eine andere Idee??
Danke und Gruß
Christian
``return`` beendet eine Funktion und gibt den Ausdruck als Rückgabewert. Kein Wunder das das nur einmal ausgeführt wird.
Gibst Du da alles einzeln an, was in so einem Key steckt? Kannst Du nicht einfach ``return self.keys.items()`` statt der Schleife schreiben?
Ansonsten wirst Du in einer Schleife erst eine Ergebnisliste erstellen müssen und diese nach der Schleife mit ``return`` zurückgeben.
Gibst Du da alles einzeln an, was in so einem Key steckt? Kannst Du nicht einfach ``return self.keys.items()`` statt der Schleife schreiben?
Ansonsten wirst Du in einer Schleife erst eine Ergebnisliste erstellen müssen und diese nach der Schleife mit ``return`` zurückgeben.
ich hab jetzt mal ne testmethode eingefügt
diese wird intern im server über die methode
listAllKeys()
aufgerufen einfach mit:
return keys.test()
testdaten:
keys.set_key("rsa", "w23", "999", "chris", "localhost")
keys.set_key("el-gamal", "h2213", "111", "martin", "192.168.0.1")
keys.set_key("idea", "f234", "222", "miri", "192.168.0.2")
keys.set_key("rsa", "wef22", "333", "geo", "192.168.0.3")
ausgabe am client:
['w23', 'h2213', 'f234', 'wef22']
schonmal nicht schlecht, aber leider nur die "keys" an sich. Ich würd gern alles haben
wenn ich die testmethode mit
return self._shelve.items()
änder, bekomm ich am client
Fault: <Fault 1: "exceptions.TypeError:cannot marshal <class '__main__.Key'> objects">
hmmm... *grübel* ideen?
[/code]
Code: Alles auswählen
def test(self):
return self._shelve.keys()
listAllKeys()
aufgerufen einfach mit:
return keys.test()
testdaten:
keys.set_key("rsa", "w23", "999", "chris", "localhost")
keys.set_key("el-gamal", "h2213", "111", "martin", "192.168.0.1")
keys.set_key("idea", "f234", "222", "miri", "192.168.0.2")
keys.set_key("rsa", "wef22", "333", "geo", "192.168.0.3")
ausgabe am client:
['w23', 'h2213', 'f234', 'wef22']
schonmal nicht schlecht, aber leider nur die "keys" an sich. Ich würd gern alles haben
wenn ich die testmethode mit
return self._shelve.items()
änder, bekomm ich am client
Fault: <Fault 1: "exceptions.TypeError:cannot marshal <class '__main__.Key'> objects">
hmmm... *grübel* ideen?
[/code]
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi dankegut!dankegut hat geschrieben:Fault: <Fault 1: "exceptions.TypeError:cannot marshal <class '__main__.Key'> objects">
XML-RPC ist ein Protokoll, mit dem Daten zwischen den verschiedensten Programmiersprachen ausgetauscht werden können. Damit das so einfach funktioniert, können keine komplexe Datentypen ausgetauscht werden.
Du kannst einen String, eine Zahl, Listen, Dictionaries, Datum und Binärdaten zurück geben. Alles andere ist Tabu.
Was die die oben aufgezeigte Meldung sagen will, ist dass du kein Objekt vom Typ "Key" zurück geben kannst.
Lösung: Wandle zuerst die Daten in eine der oben genannten Datentypen (Liste, Dictionary) um und gib die Daten dann zurück.
Siehe: http://docs.python.org/lib/module-xmlrpclib.html
mfg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
ah.. ja da war was mit den bestimmten datentypen. ich habs jetzt so gelöst.
und es klappt, nur so zur info
Code: Alles auswählen
def listAllKeys(self):
tmp = ''
for key in keys.itervalues():
tmp += str([key.algo, key.key, key.hashval, key.name, key.host]) + "\n"
bintmp = xmlrpclib.Binary(tmp)
return bintmp
Hi gerold!
Ich würde das nicht so umständlich machen sondern gleich ein "IF EXIST" einbauen. So wird die Tabelle dann nur erzeugt wenn sie auch existiert.
Hier die geändeerte Version: Funktioniert 100%ig, wiel ich meine Tabellen auch mit "IF EXIST" so erzeuge
lg
xtra
P.S.: Das hat neben der kürzeren Schreibweise noch den vorteil das ein Query weniger erzeugt werden muss.
EDIT: Falsche Einrückung von mir korrigiert.
Ich würde das nicht so umständlich machen sondern gleich ein "IF EXIST" einbauen. So wird die Tabelle dann nur erzeugt wenn sie auch existiert.
Code: Alles auswählen
def create_dbstructure(self):
"""
Erstellt die Tabellen
"""
cur = self.cur
conn = self.conn
# keys-Tabelle erstellen, falls noch nicht erstellt.
sql = """
SELECT name FROM sqlite_master
WHERE (type = 'table') AND (name = 'keys')
"""
cur.execute(sql)
if not self.cur.fetchone():
# Die Tabelle existiert noch nicht. Sie kann erstellt werden.
sql = """
CREATE TABLE keys (
key TEXT PRIMARY KEY NOT NULL,
algo TEXT,
name TEXT,
hashval TEXT
)
"""
cur.execute(sql)
# Index(e) erstellen
sql = """
SELECT name FROM sqlite_master
WHERE (type = 'index') AND (name = 'i_keys_algo')
"""
cur.execute(sql)
if not cur.fetchone():
sql = "CREATE INDEX i_keys_algo ON keys (algo)"
cur.execute(sql)
conn.commit()
Code: Alles auswählen
def create_dbstructure(self):
"""
Erstellt die Tabellen
"""
cur = self.cur
conn = self.conn
# Erstellt die Tabelle falls sie noch nicht existiert.
# Dies wird durch die Abfrage IF EXIST erreicht die glücklicherweise
# auch in SQLite funktioniert :)
sql = """
CREATE TABLE IF NOT EXISTS keys (
key TEXT PRIMARY KEY NOT NULL,
algo TEXT,
name TEXT,
hashval TEXT
)
"""
cur.execute(sql)
# Index(e) erstellen
sql = """
SELECT name FROM sqlite_master
WHERE (type = 'index') AND (name = 'i_keys_algo')
"""
cur.execute(sql)
if not cur.fetchone():
sql = "CREATE INDEX i_keys_algo ON keys (algo)"
cur.execute(sql)
conn.commit()
xtra
P.S.: Das hat neben der kürzeren Schreibweise noch den vorteil das ein Query weniger erzeugt werden muss.
EDIT: Falsche Einrückung von mir korrigiert.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi XtraNine!XtraNine hat geschrieben:Ich würde das nicht so umständlich machen sondern gleich ein "IF EXIST" einbauen.
Wenn es bei dir funktioniert, dann ist das korrekt. Leider funktioniert es bei vielen noch nicht. Deshalb habe ich es im Beispiel nicht verwendet.
Hier die Begründung: http://gelb.bcom.at/trac/misc/browser/s ... sdb.py#L79
lg
Gerold
PS: Und jetzt gehe ich wieder ins Bett, meine Grippe ausschlafen.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Hi Gerold
Ich danke dir! Das wusste ich nicht Ich werde in meinen Programm das auch ändern, damit es mit älteren Versionen von SQLite kompatibel ist.
lg
Ich danke dir! Das wusste ich nicht Ich werde in meinen Programm das auch ändern, damit es mit älteren Versionen von SQLite kompatibel ist.
Wünsch dir eine gute BesserungPS: Und jetzt gehe ich wieder ins Bett, meine Grippe ausschlafen.
lg
Also EAFP oder? Naja, die Idee ist so Simple da hätte ich auch drauf kommen können Ehrliche Meinung? Hmm, Ich benutze "try: except:" zwar auch häufig aber es ist nicht mMn ein besonders guter Stil das permanent zu benutzen. Außerdem sehen 20 "try:, except:" Blöcke einfach nur hässliche aus (wie in meine momentanen Programm das ich ändern werde ^^)jens hat geschrieben:Und die harten Jungs, erzeugen einfach die Tabelle und fangen den Fehler, wenn diese schon existiert, mit try-except ab
Aber das wäre mal ein Thema für nen neune Thread ^^ -> Wann sollte man "try, except" benutzen und wo man es vermeiden sollte ^^
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Ja, in dem Falle ist das so eine Sache. Man kann nicht gut explizit nur den Fehler "Tabelle existiert schon" abfangen. Das ist das Problem...
Letztens hatte ich aber das so gemacht:
http://pylucid.net/trac/browser/PyLucid ... v=575#L230
Funktioniert aber nur bei MySQL, es sei den SQLite wirft auch einen Fehler mit dem String "doesn't exist"...
Ist aber eh nur eine vorübergehende Lösung
Letztens hatte ich aber das so gemacht:
Code: Alles auswählen
try:
filelist = self.get_filedata()
except Exception, e:
if not "doesn't exist" in str(e):
raise Exception(e)
self.page_msg.red("Error: %s" % e)
else:
self.create_table()
Funktioniert aber nur bei MySQL, es sei den SQLite wirft auch einen Fehler mit dem String "doesn't exist"...
Ist aber eh nur eine vorübergehende Lösung
Stimmt, das ist mir auch schon aufgefallen das ein und die selber exception für verschiedene Sachen ausgelöst wird, mit unterschiedlicher Fehlermeldung
Du könntes mal kucken ob die Exception Klasse ein errno hat, oder so was ähnliches, und das dann mal abfragen. Das müsste unterschiedliche Nummern für verschiedene Fehlermeldungen beinhalten (so wie IOError wenn ich das nicht mit ner anderen exception verwechsele).
Allgemein ist die Überprüfung ob der string in der Meldung vorhanden ist, sehr unsauber. Wenn die diese Meldung bei den nächsten release änder (ok, ist unwahrscheinlich) dann funktioniert diese abfrage nicht mehr.
Aber du sagst ja bereits das es ehe nur vorübergehend ist. von daher i.O.
lg
Du könntes mal kucken ob die Exception Klasse ein errno hat, oder so was ähnliches, und das dann mal abfragen. Das müsste unterschiedliche Nummern für verschiedene Fehlermeldungen beinhalten (so wie IOError wenn ich das nicht mit ner anderen exception verwechsele).
Allgemein ist die Überprüfung ob der string in der Meldung vorhanden ist, sehr unsauber. Wenn die diese Meldung bei den nächsten release änder (ok, ist unwahrscheinlich) dann funktioniert diese abfrage nicht mehr.
Aber du sagst ja bereits das es ehe nur vorübergehend ist. von daher i.O.
lg
hallo nochmal
also ich bin soweit schon gut weiter gekommen dank eurer hilfe. Nun aber wieder n problem.
Wenn das shelve file leer ist, oder sozusagen keine Einträge vorhanden sind, krieg ich bei allen funktionen folgende Fehlermeldung:
Exception in thread Thread-1:
Traceback (most recent call last):
File "threading.py", line 442, in __bootstrap
self.run()
File "client.py", line 59, in run
print server.sendKey(key1)
File "xmlrpclib.py", line 1096, in __call__
return self.__send(self.__name, args)
File "xmlrpclib.py", line 1383, in __request
verbose=self.__verbose
File "xmlrpclib.py", line 1147, in request
return self._parse_response(h.getfile(), sock)
File "xmlrpclib.py", line 1286, in _parse_response
return u.close()
File "xmlrpclib.py", line 744, in close
raise Fault(**self._stack[0])
Fault: <Fault 1: 'exceptions.TypeError:cannot marshal None unless allow_none is enabled'>
Sobald ein Eintrag voreingestellt vorhanden ist, den ich beim Server sozusagen als dummy Eintrag erstelle klappt es, ist dieser jedoch nicht vorhanden und ich möchte über den Client den ersten Eintrag machen möchte, kommt die Fehlermeldung oben. Gibt es eine möglich dies zu umgehen
Hier mal eine Beispielmethode:
Das return statement, "Key not found" greift hier leider irgendwie noch, doch wie soll ich dass den anders abfragen?
Jemand eine Idee?
Gruß
Christian
also ich bin soweit schon gut weiter gekommen dank eurer hilfe. Nun aber wieder n problem.
Wenn das shelve file leer ist, oder sozusagen keine Einträge vorhanden sind, krieg ich bei allen funktionen folgende Fehlermeldung:
Exception in thread Thread-1:
Traceback (most recent call last):
File "threading.py", line 442, in __bootstrap
self.run()
File "client.py", line 59, in run
print server.sendKey(key1)
File "xmlrpclib.py", line 1096, in __call__
return self.__send(self.__name, args)
File "xmlrpclib.py", line 1383, in __request
verbose=self.__verbose
File "xmlrpclib.py", line 1147, in request
return self._parse_response(h.getfile(), sock)
File "xmlrpclib.py", line 1286, in _parse_response
return u.close()
File "xmlrpclib.py", line 744, in close
raise Fault(**self._stack[0])
Fault: <Fault 1: 'exceptions.TypeError:cannot marshal None unless allow_none is enabled'>
Sobald ein Eintrag voreingestellt vorhanden ist, den ich beim Server sozusagen als dummy Eintrag erstelle klappt es, ist dieser jedoch nicht vorhanden und ich möchte über den Client den ersten Eintrag machen möchte, kommt die Fehlermeldung oben. Gibt es eine möglich dies zu umgehen
Hier mal eine Beispielmethode:
Code: Alles auswählen
def receiveKey(self, key):
# check if key exists
for k in keys.itervalues():
if k.key == key:
key = keys.get_key(key)
return key.algo, key.key, key.hashval, key.name, key.host
else:
return "Key not found"
Jemand eine Idee?
Gruß
Christian
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Du pastest den falschen Code, wenn ich
richtig lese, dann scheinst du an dieser Stelle ein Problem zu haben, so dass None gesendet wird.
Wie lang ist dein Programm? Kannst du es komplett ins LodgeIt pasten?
Code: Alles auswählen
File "client.py", line 59, in run
print server.sendKey(key1)
Wie lang ist dein Programm? Kannst du es komplett ins LodgeIt pasten?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
hallo,
also das war nur eine beispielmethode. es passiert bei JEDER methode die auf das leere shelve zugreifen will. hier aber trotzdem der code
vielleicht wer ne idee?
also das war nur eine beispielmethode. es passiert bei JEDER methode die auf das leere shelve zugreifen will. hier aber trotzdem der code
Code: Alles auswählen
def sendKey(self, key_dict):
# check algorithm type
if key_dict["algo"] == "RSA":
# check if name/key already exists
for key in keys.itervalues():
if key.name == key_dict["name"]:
return "Name already exists"
else:
# save key if it doesn't exist
keys.set_rsa_key(key_dict["algo"],key_dict["key"],key_dict["hashval"],key_dict["name"],key_dict["host"])
return "successfully saved RSA Key"
if key_dict["algo"] == "ElGamal":
for k in keys.itervalues():
if k.name == key_dict["name"]:
return "Name already exists"
else:
keys.set_elgamal_key(key_dict["algo"], key_dict["key1"], key_dict["key2"],
key_dict["key3"], key_dict["hashval"], key_dict["name"], key_dict["host"])
return "successfully saved ElGamal Key"
else:
return "No valid Key"
Erstmal zu dem Quelltext: Da ist ein bzw. zwei logische Fehler enthalten. Das setzen des Schlüssels gehört bestimmt nicht in den ``else``-Zweig sondern *hinter* die Schleife, die prüft ob es die Name/Algorithmus-Kombination schon gibt.
Es gibt zweimal den selben Fehler, weil sich der entsprechende Quelltext nahezu identisch wiederholt. Die Unterschiede lassen sich herausziehen. Vom Algorithmusnamen sind die `set_*()`-Methode und die Argumente abhängig, alles andere scheint gleich zu bleiben. Das könnte man so schreiben (ungetestet):
Ich sehe in diesem Forums-Thread auch ziemlich oft, dass Du mit `itervalues()` über das `Shelve` läufst um etwas zu suchen -- nutzt Du überhaupt irgendwo sinnvoll aus, dass es sich bei einem `Shelve` um ein `Dictionary`-ähnliches Objekt handelt?
Es gibt zweimal den selben Fehler, weil sich der entsprechende Quelltext nahezu identisch wiederholt. Die Unterschiede lassen sich herausziehen. Vom Algorithmusnamen sind die `set_*()`-Methode und die Argumente abhängig, alles andere scheint gleich zu bleiben. Das könnte man so schreiben (ungetestet):
Code: Alles auswählen
def send_key(self, key_dict):
algo_map = { 'RSA': (keys.set_rsa_key, ('algo', 'key', 'hashval',
'name', 'host')),
'ElGamal': (keys.set_elgamal_key, ('algo', 'key1', 'key2',
'key3', 'hashval',
'name', 'host')) }
algo_name = key_dict['algo']
if algo_name in algo_map:
name = key_dict['name']
for key in keys.itervalues():
if key.name == name and key.algo == algo_name:
return 'Name already exists'
set_func, attr_names = algo_map[algo_name]
set_func(*[key_dict[attr_name] for attr_name in attr_names])
return 'Successfully saved %s key' % algo_name
else:
return 'No valid Key'
Modul(e) im Interpretierer importieren und die Funktionen alle mal per Hand austesten und/oder Doctests und/oder Unit-Tests schreiben.dankegut hat geschrieben:vielleicht wer ne idee?
Hallo,
hmm... danke für deinen Vorschlag. Ich seh ja ein, dass das so halb doppelt gemoppelter Code ist, aber ich bin in python auch noch nicht so fit, dass ich da sowas, wie du es jetzt geschrieben hast eben so aus der Nase saugen und implementieren kann. Ich hab das Problem jetzt zum Glück noch gelöst, durch eine length Abfrage auf das shelve.
Gruß
Christian
hmm... danke für deinen Vorschlag. Ich seh ja ein, dass das so halb doppelt gemoppelter Code ist, aber ich bin in python auch noch nicht so fit, dass ich da sowas, wie du es jetzt geschrieben hast eben so aus der Nase saugen und implementieren kann. Ich hab das Problem jetzt zum Glück noch gelöst, durch eine length Abfrage auf das shelve.
Gruß
Christian
Hast Du den logischen Fehler auch behoben!? Bei einem leeren `Shelve` wird nämlich nie ein Schlüssel gespeichert, weil die ``for``-Schleifen ja gar nicht ausgeführt werden. Dann wird auch kein explizites ``return`` ausgeführt und damit gibt die Methode `None` zurück. Das wäre wohl das Problem. Ist mir beim letzten Posting gar nicht aufgefallen.