Hallo!
Ich möchte gerne in Python eine große Anzahl von IP-Adressen und zugehörigen Port-Nummern verwalten. Ich bekomme Ranges von IP-Adressen und Port-Nummern und will dann aus diesen Tupel bilden. Also <IP:Port> eben. Jedes dieser Tupel darf aber nur einmal benutzt werden.
Irgendwie ist dieses Problem nicht so trivial wie es scheint... die Datenmengen können nämlich sehr groß werden... von den Port-Nummern gibt es ja schon alleine 65 Tausend...
Welche Datenstruktur könnte ich dafür in Python benutzen... ?
Stehe da im Moment voll auf dem Schlauch... über jede Anregung wäre ich dankbar!
mfg elLobo
Problem: Große Anzahl von IP-Adressen verwalten!
Ahh... Set... kannte ich noch gar nicht... danke!Leonidas hat geschrieben:Dazu nimmst du am besten ein Set (= Menge), dadurch wird garantiert, dass es jede Tupel nur einmal im Set gibt.
Aber damit habe ich doch auch das Problem, wenn ich zuviele IPs und Ports habe, die Datenmengen sehr groß werden.... hat jemand Erfahrungswerte, bis zu welcher Größe ich in Python z.B. eine Liste mit Integerwerten füllen kann, bis mir alles abschmiert?
mfg elLobo
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Solange dir das Virtual Memory mitspilet. Auf 32-Bit Systemen hat jeder Prozess 2 GB Speicher zur verfügung, wenn du drüber kommst: schlecht.
Allerdings rate ich dir von Listen ab, nimm dafür eben besser Sets.
Allerdings rate ich dir von Listen ab, nimm dafür eben besser Sets.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Worst-Case: Klasse-A-Netz -> 16.774.214 Adressen x 65.536 Port-Nummern = ca. 1 Billion Tupel.Leonidas hat geschrieben:Solange dir das Virtual Memory mitspilet. Auf 32-Bit Systemen hat jeder Prozess 2 GB Speicher zur verfügung, wenn du drüber kommst: schlecht.
Allerdings rate ich dir von Listen ab, nimm dafür eben besser Sets.

Je Tupel 8 Byte Speicherbedarf -> ca. 8 Tebibyte

Selbst ein Klasse-B-Netz würde den Rahmen von 2Gb sprengen...
Habe noch nie so große Datenmengen verwalten müssen...
mfg elLobo
Hmmm.... werde ich mir anschauen... aber eigentlich wollte ich auf eine Datenbank verzichten... Danke für den Tip!jens hat geschrieben:Oder gleich direkt eine Datenbank! Vielleicht SQLite...
mfg elLobo
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
http://sqlite.org
Supports databases up to 2 terabytes (241 bytes) in size.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi elLobo!elLobo hat geschrieben: Irgendwie ist dieses Problem nicht so trivial wie es scheint... die Datenmengen können nämlich sehr groß werden... von den Port-Nummern gibt es ja schon alleine 65 Tausend...
Welche Datenstruktur könnte ich dafür in Python benutzen... ?
Du könntest "shelve" verwenden. Shelve verhält sich wie ein Dictionary, speichert die Daten aber in ein File-Objekt ab. Das Lesen von einzelnen Werten aus diesem Objekt ist ziemlich schnell. Ich habe das Ganze mit 1 Mio. Datensätze unter Linux ausprobiert.
Hier ein Beispiel:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
import shelve
# Schreiben
sh = shelve.open("filename", protocol = 2)
sh["Vorname"] = "Nudelaug"
sh["Nachname"] = "Thompson"
sh.close()
# Lesen
sh = shelve.open("filename", protocol = 2)
print sh["Vorname"]
print sh["Nachname"]
sh.close()
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
******************************************************************************
* Description: Shelve-Test
* Help: http://www.python.org/doc/current/lib/module-shelve.html
******************************************************************************
"""
import os
import os.path
import shelve
FILENAME = "shelvefile"
MAX = 200000
PROTOCOL = 2
#----------------------------------------------------------------------
def fill_shelve(key = None, value = None):
"""
Befüllt das Objekt mit Daten.
"""
sh = shelve.open(FILENAME, protocol = PROTOCOL)
print "fill - begin"
if key is None:
for i in range(MAX):
sh[str(i)] = "Eintrag Nummer %s" % i
if i % 1000 == 0:
print "fill - %s" % i
else:
sh[key] = value
sh.close()
print "fill - end"
#----------------------------------------------------------------------
def read_shelve(direction = "asc", additional_keys = None):
"""
Liest ein paar Daten aus dem Shelve aus.
"""
sh = shelve.open(FILENAME, protocol = PROTOCOL)
print "read - begin"
if direction == "asc":
for i in range(0, MAX, 1500):
print "read - %s = %s" % (i, sh[str(i)])
else:
for i in range(MAX - 1, 0, -1500):
print "read - %s = %s" % (i, sh[str(i)])
if additional_keys:
for key in additional_keys:
print "read - %s = %s" % (key, sh[key])
sh.close()
print "read - end"
#----------------------------------------------------------------------
def main():
"""
Hauptprozedur
"""
if not(os.path.isfile(FILENAME)):
fill_shelve()
fill_shelve("Vorname", "Nudelaug")
fill_shelve("Nachname", "Thompson")
read_shelve("asc")
read_shelve(
"desc",
(
"Vorname",
"Nachname"
)
)
#----------------------------------------------------------------------
if __name__ == "__main__":
main()
mfg
Gerold

Edit: Protokoll auf das schnellere Binary-Protokoll gesetzt.
Edit2: Um Shelve eine bessere Chance zu geben, habe ich ein Kurzbeispiel eingefügt.
Zuletzt geändert von gerold am Dienstag 3. Januar 2006, 21:51, insgesamt 3-mal geändert.
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.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Dabei würde ich aber das beachten: http://www.python.org/doc/current/lib/node64.htmlgerold hat geschrieben:Du könntest "shelve" verwenden.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi Jens!jens hat geschrieben:Dabei würde ich aber das beachten: http://www.python.org/doc/current/lib/node64.html
Danke, habe ich ins Beispiel eingebaut.
lg
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.
-
- User
- Beiträge: 1790
- Registriert: Donnerstag 28. Oktober 2004, 16:33
- Wohnort: Graz, Steiermark - Österreich
- Kontaktdaten:
Für so große Datensätze und für so einfachen aufbau würde ich ein Array nehmen. Die Dinger nutzen den Speicher besser, da keine Referenzen und Objekte abgelegt werden, sondern wirklich nur die Werte.
Code: Alles auswählen
>>> from array import array
>>> iplist = []
>>> iplist.append(array("B", [255, 255, 255, 255]))
>>> iplist.append(array("B", [0, 0, 0, 0]))
>>> iplist
[array('B', [255, 255, 255, 255]), array('B', [0, 0, 0, 0])]
TUFKAB – the user formerly known as blackbird
Bei so einer grossen Datenmenge sind auch Arrays nix. Die müssten dann alle in den Speicher passen. Und wenn man das Array dynamisch vergrössert, muss unter Umständen sogar 3x soviel Speicher vorhanden sein, damit das klappt.
elLobo hat noch nicht geschrieben, was er mit den Daten eigentlich machen will. Wenn man zum Beispiel als Anforderung hat, alle Portnummern zu einer gegebenen IP herauszufinden, dann ist das lineare Suchen in Arrays oder Listen von diesen Ausmassen *äusserst* ungünstig.
Ich würde mich dem Vorschlag mit der Datenbank anschliessen. Die sind für solche Datenmengen gedacht.
elLobo hat noch nicht geschrieben, was er mit den Daten eigentlich machen will. Wenn man zum Beispiel als Anforderung hat, alle Portnummern zu einer gegebenen IP herauszufinden, dann ist das lineare Suchen in Arrays oder Listen von diesen Ausmassen *äusserst* ungünstig.
Ich würde mich dem Vorschlag mit der Datenbank anschliessen. Die sind für solche Datenmengen gedacht.
Es sollen aus einer Liste von gültigen IPs und Ports entsprechende Tupel gebildet werden und diese einem "anderem System" zur Verfügung gestellt werden.BlackJack hat geschrieben: elLobo hat noch nicht geschrieben, was er mit den Daten eigentlich machen will. Wenn man zum Beispiel als Anforderung hat, alle Portnummern zu einer gegebenen IP herauszufinden, dann ist das lineare Suchen in Arrays oder Listen von diesen Ausmassen *äusserst* ungünstig.
I
Ich denke man kann an die Sache aus zwei Richtungen ran gehen:
1. Ich bilde aus allen gültigen IPs und Ports ein Tupel und kontrolliere, ob dieses schon benutzt wurde, falls nicht, wird es in eine "Blacklist" eingetragen. Der Vorteil hierbei wäre, dass die Datenmenge recht lansgam steigt, aber mit der Zeit es immer schwieriger wird, ein noch nicht benutztes Tupel zu finden, also steigt auch der Aufwand...
2. Ich erstelle gleich von Beginn an, eine komplette Liste mit allen gültigen Tupeln und lösche dann nach und nach alle benutzten raus. Nachteil, ich brauche verdammt viel Speicherplatz...
Welche Version scheint sinnvoller?
Danke soweit für die Tips... werde mir das alles anschauen...
mfg elLobo
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi elLobo!elLobo hat geschrieben:Es sollen aus einer Liste von gültigen IPs und Ports entsprechende Tupel gebildet werden und diese einem "anderem System" zur Verfügung gestellt werden.
Du schreibst nur, wie du an die Sache ran gehen würdest, aber nicht, wofür du es wirklich brauchst. So können wir dir keinen besseren Vorschlag geben.
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.
Naja... das steckt nix tieferes hinter... letzendes soll halt ein bestehendes Programm um die Fähigkiet erweitert werden, wie oben beschrieben, IP-Adressen zu verwalten...gerold hat geschrieben:Hi elLobo!elLobo hat geschrieben:Es sollen aus einer Liste von gültigen IPs und Ports entsprechende Tupel gebildet werden und diese einem "anderem System" zur Verfügung gestellt werden.
Du schreibst nur, wie du an die Sache ran gehen würdest, aber nicht, wofür du es wirklich brauchst. So können wir dir keinen besseren Vorschlag geben.
mfg
Gerold
Eure Tips schaue ich mir morgen an und wenn ich dann noch Fragen habe, schreib ich nochmal.... was am Ende daraus geworden ist, erfahrt ihr dann auch noch.

mfg elLobo
Die Frage bleibt: Warum? Was ist der Sinn und Zweck? Wie werden die Adressen "erzeugt"? In welcher Reihenfolge? Werden überhaupt alle Möglichkeiten erzeugt? Was heisst einem anderem System zur Verfügung stellen?
Das jemand wirklich alle IP-Adressen + Portnummern einfach so als Daten haben möchte klingt zumindest komisch.
Ansonsten würde ich das ganze "Klassenweise" als Bitset auf der Platte verwalten. Für ein einzelnes Klasse A Netz wären das "nur" ca. 128 Gigabyte. Platten in der Grössenordnung sind ja nicht mehr sooo exotisch. Wenn Du 256 Stück davon einbaust, dann kannst Du das gesamte Netz erfassen. Naja IPv4 zumindest.
Das jemand wirklich alle IP-Adressen + Portnummern einfach so als Daten haben möchte klingt zumindest komisch.
Ansonsten würde ich das ganze "Klassenweise" als Bitset auf der Platte verwalten. Für ein einzelnes Klasse A Netz wären das "nur" ca. 128 Gigabyte. Platten in der Grössenordnung sind ja nicht mehr sooo exotisch. Wenn Du 256 Stück davon einbaust, dann kannst Du das gesamte Netz erfassen. Naja IPv4 zumindest.

- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Das hast du aber schön gesagt.BlackJack hat geschrieben:Naja IPv4 zumindest.

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.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Mir ist auch unklar, was du eigentlich machen willst... Aber generell finde ich diesen Ansatz schon ganz gut.elLobo hat geschrieben:1. Ich bilde aus allen gültigen IPs und Ports ein Tupel und kontrolliere, ob dieses schon benutzt wurde, falls nicht, wird es in eine "Blacklist" eingetragen. Der Vorteil hierbei wäre, dass die Datenmenge recht lansgam steigt, aber mit der Zeit es immer schwieriger wird, ein noch nicht benutztes Tupel zu finden, also steigt auch der Aufwand...
Vielleicht solltest du allerdings jede IP mit einem timestamp versehen. Wenn du eine echte Datenbank benutzt ist es eine Kleinigkeit automatisch veraltete IP-Adressen zu löschen. Ich meine IP-Adressen sind in der Regel relativ flüchtig.
Außerdem kannst du dir die letzte Freie IP-Adresse seperat festhalten und von da an, die nächste freie Suchen... Macht ja keinen Sinn ständig von Null an zu fangen

-
- User
- Beiträge: 670
- Registriert: Sonntag 15. Januar 2006, 18:42
- Wohnort: Celle
- Kontaktdaten:
Hi OP!
Ich hab für mein Projekt PyFWBuilder eine Set-Klasse geschrieben die für Integers gedacht ist, und ich hab auch eine kleine Erweiterung für IP-Ranges oben drauf. Das Ding ist unter:
http://aspn.activestate.com/ASPN/Cookbo ... ipe/466298
und
http://aspn.activestate.com/ASPN/Cookbo ... ipe/466286
zu finden. Was genau Du willst ist denke ich nicht implementiert, aber wenn Du effizient port/ip paare speichern willst ist es sicherlich ein einfaches die IP4Range-Klasse soweit zu ändern dass sie noch <ip>:<port> akzeptiert. Daraus erstellst Du dann eine Zahl in der Form:
<port><ip>
Zum Beispiel (in Hex-Notation):
172.22.162.250:50
würde zu
0x0032ac16a2fa
Diese Zahl speicherst Du dann im integer set.
Du ein ganzes Subnet mit einem Port hast würde dass zum Beispiel für:
172.22.162.0/24:50
folgende Zahlen bedeuten:
0x0032ac16a200 - 0x0032ac16a2ff
Das lässt sich natürlich sehr effizient in einem Integer set speichern, und es ist sogar halbwegs sinnvoll darüber Mengen-Relationen zu bilden. Und: die Klasse hat ein einfaches iterator-Protokoll in IntSet bereits vorimplementiert. Du könntest also einfach über das set iterieren, und so alle Hosts die zu fragen sind rauskriegen.
Wenn noch Fragen sind, frag!
--- Heiko.
Ich hab für mein Projekt PyFWBuilder eine Set-Klasse geschrieben die für Integers gedacht ist, und ich hab auch eine kleine Erweiterung für IP-Ranges oben drauf. Das Ding ist unter:
http://aspn.activestate.com/ASPN/Cookbo ... ipe/466298
und
http://aspn.activestate.com/ASPN/Cookbo ... ipe/466286
zu finden. Was genau Du willst ist denke ich nicht implementiert, aber wenn Du effizient port/ip paare speichern willst ist es sicherlich ein einfaches die IP4Range-Klasse soweit zu ändern dass sie noch <ip>:<port> akzeptiert. Daraus erstellst Du dann eine Zahl in der Form:
<port><ip>
Zum Beispiel (in Hex-Notation):
172.22.162.250:50
würde zu
0x0032ac16a2fa
Diese Zahl speicherst Du dann im integer set.
Du ein ganzes Subnet mit einem Port hast würde dass zum Beispiel für:
172.22.162.0/24:50
folgende Zahlen bedeuten:
0x0032ac16a200 - 0x0032ac16a2ff
Das lässt sich natürlich sehr effizient in einem Integer set speichern, und es ist sogar halbwegs sinnvoll darüber Mengen-Relationen zu bilden. Und: die Klasse hat ein einfaches iterator-Protokoll in IntSet bereits vorimplementiert. Du könntest also einfach über das set iterieren, und so alle Hosts die zu fragen sind rauskriegen.
Wenn noch Fragen sind, frag!
--- Heiko.