allgemeine fragen zu klassen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
naked_chef
User
Beiträge: 15
Registriert: Dienstag 3. Februar 2009, 10:02

hi,

ich befasse mich gerade etwas mit klassen und habe da anscheinend ein kleines versändnissproblem:

ich möchte auf einem entfernten host, per ssh zugreiffen, befehle ausführenlassen und den output auswerten bzw. anzeigen lassen.

mit paramiko hab ich dafür auch schon das passende werkzeug gefunden.
in einer funktion verpackt klappt auch das importieren und nutzen des modules.

jetzt möchte ich nicht jedesmal die verbindung neu initialisieren müssen wenn ich mehrere abfragen hintereinander mache. da die reihnfolge variiert ist es auch nicht da ziel alle möglichen variationen in unterschiedliche funktionen zu packen.

also eine klasse. (ich hoffe, dass das der richtige weg ist)



Code: Alles auswählen

import paramiko

class Ssh(object):

        def __init__(self, host, sysuser):
                paramiko.util.log_to_file('paramiko.log')
                client = paramiko.SSHClient()
                client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                client.connect(hostname=host, username=sysuser, key_filename='~/.ssh/id_rsa')

        def get_current_auth(self):
                stdin, stdout, stderr = client.exec_command('cat ~/.ssh/authorized_keys')
                type(stdin)
                res = stdout.readlines()
                return res

        def __del__(self):
                client.close()
ich kann die klasse/verbindung initialisieren.
wenn ich die methode "get_current_auth" ausführen möchte, bekomme ich die meldung, dass "client" nicht definiert ist.

das sind meine ersten gehversuche mit klassen, daher hab ich bestimmt irgendwo einen gravierenden denkfehler.

kann ich meine vorstellung überhaupt mit einer klasse umsetzen ?

gruss naked
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Es sollte statt "client" immer "self.client" heißen. Ohne das "self" ist der Name lokal, mit self gehört er zum Objekt.

"__del__" solltest du übrigens nicht verwenden, es ist nicht garantiert, dass es jemals aufgerufen wird. Füge besser eine Methode hinzu, mit der du explizit die Verbindung beenden kanst.
Das Leben ist wie ein Tennisball.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

`__del__` sollte man nicht nutzen, zum Einen ist nicht garantiert, wann oder ob sie beim aufräumen aufgerufen wird und zum anderen kann man sich damit wunderbar zirkuläre Abhängigkeiten aufbaun.

`client` ist in `__init__` ein lokaler Name, darum kannst du ihn in `get_current_auth` nicht aufrufen. Stelle deinen Namen, die an das Exemplar gebunden werden sollen ein `self.` vor und es klappt.

Das kannst du mit Klassen umsetzen, die Frage ist allerdings, ob die überhaupt eine benötigst.
naked_chef
User
Beiträge: 15
Registriert: Dienstag 3. Februar 2009, 10:02

cofi hat geschrieben: Das kannst du mit Klassen umsetzen, die Frage ist allerdings, ob die überhaupt eine benötigst.
wieso ?

ich habe meine klassen entsprechend angepasst und jetzt klappt es.

Code: Alles auswählen

import paramiko

class Ssh(object):

        def __init__(self, host, sysuser):
                paramiko.util.log_to_file('paramiko.log')
                self.client = paramiko.SSHClient()
                self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                self.client.connect(hostname=host, username=sysuser, key_filename='/var/www/.ssh/id_rsa')

        def get_current_auth(self):
                stdin, stdout, stderr = self.client.exec_command('cat ~/.ssh/authorized_keys')
                type(stdin)
                res = stdout.readlines()
                return res

        def close(self):
                self.client.close()

        def __del__(self):
                pass
nur nochmal zum verständniss.
wenn ich eine methode mit "self." ausführe ist sie klassen weit verfügbar.
ohne nur in der aktuellen methode ?

danke.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Du solltest auf eine __del__ Methode besser verzichten. Die kann erstaunlich oft dazu führen dass der GC nicht mehr alles aufräumt.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

naked_chef hat geschrieben:nur nochmal zum verständniss.
wenn ich eine methode mit "self." ausführe ist sie klassen weit verfügbar.
ohne nur in der aktuellen methode ?
Wenn du eine Methode mit self aufrufst dann muss diese Methode in der Instanz der Klasse definiert sein.

Wenn du in einer Methode eine Zuweisung zu self.variablenname durchführst dann kannst du in allen Methoden dieser Instanz mit self.variablenname darauf zugreifen.
naked_chef
User
Beiträge: 15
Registriert: Dienstag 3. Februar 2009, 10:02

okay - alles verstanden.

und die __del__-methode ist gelöscht.

in vielen erklärungen stand halt das man __del__ einfach als leere funktion angeben soll und wenn man das erstemal mit klassen zutun hat, glaubt man natürlich alles.

danke für die hilfe und die hinweise
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

naked_chef hat geschrieben:in vielen erklärungen stand halt das man __del__ einfach als leere funktion angeben soll und wenn man das erstemal mit klassen zutun hat, glaubt man natürlich alles.
War das vielleicht zufälligerweise das OpenBook von Galileo? Wenn ja, weg damit, das ist Schrott... Zur Einführung in Python ist "A Byte of Python" sehr gut.
lunar

ice2k3 hat geschrieben:Wenn ja, weg damit, das ist Schrott...
Und es gibt sogar eine Begründung dafür ;)
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

lunar hat geschrieben:
ice2k3 hat geschrieben:Wenn ja, weg damit, das ist Schrott...
Und es gibt sogar eine Begründung dafür ;)
Wobei die "average"-Funktion des Authors auch nicht viel besser ist. Zuwas gibt es "sum" und "len"...

Edit: Das ist ja von BlackJack...
Warum nicht so:

Code: Alles auswählen

def average(iterable, start=0):
    return sum(iterable, start) / len(iterable)
Edit2:
Für eine "echte" Durchschnittsfunktion wäre eine explizite Float-Konvertierung oder ein

Code: Alles auswählen

from __future__ import division
auch noch notwendig.
lunar

@ice2k3: Überlege mal, welche Typen Deine Funktion und welche Typen BlackJacks Funktion verarbeiten kann. BlackJacks Funktion ist besser :)

Im Bezug auf die Fleißkommadivision dagegen hast Du meines Erachtens Recht.
naked_chef
User
Beiträge: 15
Registriert: Dienstag 3. Februar 2009, 10:02

der part mit der objektorientierung ist tatsächlich aus diesem buch - schande über mein haupt

ich muss aber zugeben, dass das ich das openbook schnell wieder geschlossen habe als mir auffiel das es viele ungereimtheiten in den verwendeten beispielen gab.

ausser für das thema OOP hab ich es nochmal rausgeholt - und anscheinend war auch das falsch.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

naked_chef hat geschrieben:ausser für das thema OOP hab ich es nochmal rausgeholt - und anscheinend war auch das falsch.
Dort ist es im Besonderen schlimm, da die Autoren Java in Python-Syntax schreiben und es sich hier am stärksten niederschlägt.

Ob du eine Klasse benötigst hängt davon ab, was du machen willst, das lässt sich daraus noch nicht ablesen - auch wenn der Code es IMHO atm noch nicht rechtfertigt.
naked_chef
User
Beiträge: 15
Registriert: Dienstag 3. Februar 2009, 10:02

okay dann muss ich leider etwas weiter ausholen, allerdings ist das dann dafür wahrscheinlich das falsche unterforum.

ich habe den auftrag ein verwaltungstool für ssh zugänge zu erstellen.
da ich mit python auf der commandline gut erfahrungen gemacht habe war die sprache meiner wahl python.

nachdem ich (auch dank dem forum hier) es geschafft habe die vorgabe von mod_python zu kippen und stattdessen auf django umgestiegen bin, kamen halt klassen ins spiel, vor diese habe ich mich bisher erfolgreich gedrückt.

dank django muss ich mich im solche sachen wie DB anbindung zum glück nicht weiter kümmern. allerdings würde ich halt ein einhaltliches interface haben wollen und müsste daher ein ssh-modul so verfassen dass ich es möglichst auch über das django-admin-interface verwaltbar ist. -klassen-

in einer DB sind user (username, voller name, mail, und public key), sowie host (hostname, location) hinterlegt. um keine inkonsistenzen zu erzeugen hole ich die aktuellen systemuser von den hosts per ssh.

anhand eines interfaces soll dann der user aus der datenbank einen systemuser auf einem host aus der datenbank zugeordnet, eine neue authorized_keys erzeugt und auf den host an den entsprechenden systemuser weiter gegeben werden.

und als sysadmin - und neuling im bereich der OOP gibt es halt viele fragen die ich gerade stück für stück beantworte. ab jetzt aber nicht mehr mit dem openbook.

zum glück ist django gut dokumentiert und es geht langsam vorran.
Antworten