Seite 1 von 1
socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Mittwoch 13. Juni 2012, 14:13
von mcdaniels
Hallo Pythonprofis,
ich habe heute aus Übungszwecken versucht, mir ein Programm zu schreiben, dass mir aus einem gegebenen Adressbereich, Hostname und IP Adresse in eine Datei schreibt. Dabei habe ich auf das Modul Socket bzw. auf die Methode gethostbyaddr von socket zurückgegriffen.
Dabei ist mir nun aufgefallen, dass -wenn es keinen DNS Eintrag für Host X gibt- eine ziemliche "Verzögerung" auftritt bis zur nächsten IP gesprungen wird. Habe dann hier im Forum gefunden, dass das wohl ein normales Verhalten von gethostbyaddr ist. Gut.
Nun mal hier mein Werk:
Code: Alles auswählen
import socket
def file_open():
try:
datafile = open('c:/hosts.txt','w')
except IOError:
print 'Pfad, Dateimodus oder Dateiname ungültig!'
return datafile
def net_range():
net_part = raw_input('Netzwerk - (Bsp. 192.168.0.): ')
host_from = raw_input('Hosts von - (Bsp. 1): ')
host_to = raw_input('Hosts bis - (Bsp. 254): ')
return net_part, host_from, host_to
def file_close():
datafile.close()
print 'Beendet!'
def discover():
datafile = file_open()
netrange = net_range()
net_part = netrange[0]
host_from = netrange[1]
host_to = netrange[2]
for host in range(int(host_from), int(host_to)):
try:
host_to_check = str(net_part) + str(host)
host_check = socket.gethostbyaddr(host_to_check)
print 'DNS zu IP {} gefunden'.format(host_to_check)
print >> datafile, host_check
except socket.herror:
print 'Für {} kein DNS - Eintrag vorhanden!'.format(host_to_check)
print >> datafile, 'Für {} kein DNS - Eintrag vorhanden!'.format(host_to_check)
except socket.gaierror:
print 'Sie haben bei der Eingabe des Adressbereichs einen Fehler gemacht!'
break
datafile.close()
Was mich in Sachen Returnwerte bzw. Module interessieren würde (auch wenn das dann eher in das Allgmeinforum gehört): Passt das so, wie ich das handhabe? Ich finde das bislang immer noch verwirrend. Ich baue eine Modul. Dieses Modul hat einen Returnwert. Um auf den Wert zuzugreifen, muss ich das Modul bzw. eigentlich dessen Returnwert an eine Variable "binden" > Globale Variablen sind böse, deshalb also so:
Code: Alles auswählen
def discover():
datafile = file_open()
netrange = net_range()
net_part = netrange[0]
host_from = netrange[1]
host_to = netrange[2]
...mir fallen dann oft keine sinnvollen Variablennamen ein... siehe zb. netrange = net_range(). Habt ihr da ev. Tips für mich?
Deshalb nochmals die Frage, ob das so ok ist?
Btw. mir ist bewusst, dass die For Schleife -wenn ich zb von 1 bis 10 eingebe, von 0 - 9 "zählt", allerdings habe ich für dieses "Problem" noch keine Lösung. (Den Wert der Variable host_to mittels +1 zu erhöhen, ist wohl eher nicht so schön...)
LG und Danke!
Daniel
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Mittwoch 13. Juni 2012, 14:53
von deets
Zuerstmal kannst du in Python Tupel-Unpacking machen:
Du kannst dir also den Zwischenschritt ueber netrange sparen.
Und deine range-Probleme verstehe ich nicht. Was du schreibst ist auch falsch: wenn du range(1, 10) machst, dann kommt da nicht 0-9, sondern 1-9 raus. Wenn du also von a nach b willst, machst du "range(a, b+1)". Was ist daran problematisch?
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Mittwoch 13. Juni 2012, 14:59
von mcdaniels
dann kommt da nicht 0-9, sondern 1-9 raus
Sorry, hast natürlich recht. Gemeint habe ich aber genau das. Mir kommt vor, ich hätte mal gelesen, dass diese Lösung mit dem "+1" nicht so "schön" ist, kann ich aber natürlich auch irren.
Ist denn grundsätzlich das Vorgehen betreffend Modularisierung + die entsprechende Übergabe der Variablen / Returnwertverarbeitung in Ordnung.
Danke dir für deine Rückemldung!
Daniel
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Mittwoch 13. Juni 2012, 15:02
von deets
Noe, da ist noch so manches im argen. Das geht damit los, dass du in file_open eine exception einfach wegschluckst. Spar dir die ganze funktion, und mach in discover lieber ein with-statement um deine schleife rum. Auch sollte discover() die host-from und to's besser von aussen reingereicht bekommen, genauso wie den filenamen.
Last but not least: wieso sollte +1 boese sein?
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Mittwoch 13. Juni 2012, 15:31
von BlackJack
@mcdaniels: Zur Terminologie: Du baust kein Modul das einen Rückgabewert hat. *Funktionen* (und Methoden) haben Rückgabewerte, Module haben das nicht, denn Module kann man auch gar nicht aufrufen.
Die Aufteilung ist nicht ganz in Ordnung, denn `file_open()` und `file_close()` funktionieren so nicht. Ich sehe auch denn Sinn von beiden nicht wirklich. Wenn innerhalb von `file_open()` ein `IOError` auftritt, dann wird der nicht behandelt, sondern ein Text ausgegeben und die Funktion bricht dann unweigerlich mit einem Fehler ab, weil `datafile` nicht bekannt ist. Das ist also nicht nur keine vernünftige Fehlerbehandlung, sondern es kommt auch gleich noch zu einem Folgefehler der dem Benutzer dann um die Ohren fliegt.
`file_close()` führt so wie es da steht zu einem `NameError`, denn `datafile` wird nirgends definiert, also weder auf Modulebene — was auch gut so ist — noch wird es als Argument übergeben.
Das sollte man alles in `discover()` mit Hilfe der ``with``-Anweisung machen.
Statt `range()` würde ich `xrange()` verwenden. Bei `host_to_check` ist ein `str()`-Aufruf überflüssig.
Die ``>>``-Syntax bei ``print`` würde ich nicht verwenden. Da würde ich die entsprechende Methode auf dem Dateiobjekt aufrufen und das Zeilenende explizit hinzufügen.
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Mittwoch 13. Juni 2012, 16:52
von mcdaniels
@deets: an +1 ist somit nichts böse

@blackjack: Natürlich schreibe ich Funktionen und keine Module... Ei, ei ei...
Muss das Programm auf jeden Fall noch überarbeiten...
Vielen Dank für Eure Rückmeldungen.
LG
Daniel
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Donnerstag 14. Juni 2012, 08:45
von mcdaniels
Hallo,
ich hab das Ganze jetzt mal ein wenig überarbeitet. Sieht nun so aus:
Code: Alles auswählen
import socket
def net_range():
net_part = raw_input('Netzwerk - (Bsp. 192.168.0.): ')
host_from = raw_input('Hosts von - (Bsp. 1): ')
host_to = raw_input('Hosts bis - (Bsp. 254): ')
return net_part, host_from, host_to
def discover():
netrange = net_range()
net_part, host_from, host_to = netrange
with open ('c:/hosts.txt','w') as datafile:
for host in xrange(int(host_from), int(host_to)+1):
host_to_check = net_part + str(host)
try:
host_check = socket.gethostbyaddr(host_to_check)
datafile.write(str(host_check)+'\n')
except socket.herror:
print 'Kein Dns-Eintrag für {}'.format(host_to_check)
except socket.gaierror:
print 'Fehlerhafte Eingabe bei den Netzwerkadressen!'
break
print 'DNS zu IP {} gefunden'.format(host_to_check)
if __name__ == "__main__":
discover()
Allerdings sind mir ein paar Dinge noch nicht klar:
@deets:
Auch sollte discover() die host-from und to's besser von aussen reingereicht bekommen, genauso wie den filenamen.
Du meinst, ich soll diese Werte der Funktion 'discover()' als Argument mitgeben? Also in der Form:
Wie bekomme ich diese Returnwerte der Funktion netrange() aber da rein ohne die Funktion an etwas zu binden? Stehe grade auf dem Schlauch... Oder sollte ich die Variablen, die ich dann der Funktion übergebe (host_from... etc) global definieren? In diesem Zusammenhang stellt sich mir die Frage, wann eine globale Variable nicht gut ist bzw. wann man auf globale Variablen zurück greift und wann nicht.
LG
Daniel
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Donnerstag 14. Juni 2012, 08:53
von deets
Ja, du sollst sie von aussen reinreichen. Ueberleg doch mal eine Sekunde lang: wenn du deine Funktion zB in einem groesseren Programm verwendest, dass im Hintergrund laeuft und seine Daten statt aus einer Eingabe aus einer Konfigurationsdatei einlist - dann ist deine Funktion schon wieder nutzlos.
Und das ist auch verwandt damit, warum global schlecht ist: globale Variablen koppeln Dinge aneinander, von denen man dann nicht mehr nachvollziehen kann, *wie* sie aneinanderhaengen. Da benennst du eine globale Variable um, oder belegst gedankenlos deren Wert neu - und schon krachts.
Fuer dein konkretes Mini-Skript ist es schon voellig ok zu schreiben
Code: Alles auswählen
net_part, host_from, host_to = net_range()
discover(net_part, host_from, host_to)
Aber wenn du globale Variablen vermeiden willst (und offensichtlich faellt dir der Gedanke so schwer, dass du das unbedingt tun *solltest*, um mal die Denke auf die Kette zu kriegen), dann machst du's halt so:
Code: Alles auswählen
def main():
net_part, host_from, host_to = net_range()
discover(net_part, host_from, host_to)
if __name__ == "__main__":
main()
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Donnerstag 14. Juni 2012, 09:20
von mcdaniels
Hey deets,
danke dir für die wertvollen Infos!
Gibt noch einiges anzupassen. Schön langsam scheine ich aber dann doch noch zu kapieren, wie es zumindest in diesem Fall läuft. Sollte eine Übung zum Thema Funktionen, Methoden, Tupel, Wertübergabe etc sein. (steter Tropfen...). Für Profis lächerlich, für mich ein Erfolgserlebnis
An alle Anfänger und Mitstreiter: Nur nicht die Flinte ins Korn werfen, auch wenn man noch so oft gegen eine Wand rennt.
LG
Daniel
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Donnerstag 14. Juni 2012, 09:45
von jens
btw. nach raw_input würde ich dann auch ein wenig validieren. z.B. int() dort machen.
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Donnerstag 14. Juni 2012, 10:38
von mcdaniels
Hallo,
hab das jetzt mal so gelöst (geht aber sicher schöner, nehme ich an):
Code: Alles auswählen
def net_range():
net_part = raw_input('Network - (Example: 192.168.0.): ')
try:
host_from = int(raw_input('Hosts from - (Example: 1): '))
host_to = int(raw_input('Hosts to - (Example: 254): '))
except ValueError:
print 'Error: You have to input a number! - starting again'
net_range()
return net_part, host_from, host_to
LG
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Donnerstag 14. Juni 2012, 11:02
von jens
Das ist nicht optimal gelöst und es fehlt auch ein return
IMHO sollte nach jeder Eingabe direkt geprüft werden. Wenn ungültig, dann soll der user den wert erneut eingeben.
btw. vielleicht ist eine CLI noch sinnvoller...
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Donnerstag 14. Juni 2012, 12:30
von mcdaniels
Ups, da ist mir ein Return entwischt, richtig.
Re: socket.gethostbyaddr - "DNS Inventarisierung"
Verfasst: Donnerstag 14. Juni 2012, 14:52
von deets
Und es ist rekursiv.... Theoretisch kommst du damit an grenzen. Darum: while Schleife draus machen.