sehr allgemeine Frage: python oder doch was anderes?

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
pau_

Donnerstag 30. Juni 2005, 13:28

Hi,

ich muss demnächst viel mit Datenbanken rumspielen. Typischerweise habe ich Files mit 40 Spalten und bis auf 4 Millionen Zeilen. Ich muss zB 9000 Zahlen von der ersten Spalte auswählen und sie mit einer Zahl multiplizieren und dann ein output File mit ihnen als erste Spalte und sowas derartiges in einer zweiten Spalte erzeugen.

Natürlich will ich das nicht per Hand und mit einem Tachenrechner machen :lol:

Welche Sprache wäre am Besten für mich? python? ruby? perl?... fortran??

Ich wollte perl vermeiden, weil man eine Sache auf viele verschiedene Arte machen kann aber ich habe gelesen, python muss das Data File am Stück aufmachen und das wird eine Weile dauern, wenn die Files so gross sind.

Ich will was Schnelles und Einfaches zum Lernen...

Irgendein Ratschlag?

Danke,

Pau
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Donnerstag 30. Juni 2005, 14:53

pau_ hat geschrieben:Hi,

ich muss demnächst viel mit Datenbanken rumspielen. Typischerweise habe ich Files mit 40 Spalten und bis auf 4 Millionen Zeilen. Ich muss zB 9000 Zahlen von der ersten Spalte auswählen und sie mit einer Zahl multiplizieren und dann ein output File mit ihnen als erste Spalte und sowas derartiges in einer zweiten Spalte erzeugen.

Natürlich will ich das nicht per Hand und mit einem Tachenrechner machen :lol:
...
Ich will was Schnelles und Einfaches zum Lernen...

...
Hi pau_,

ich geh mal davon aus, dass Du für diese Abfragen auch einen entpsrechenden Datenbank Server mit entpsrechender Hardware verwendest :?: :wink: . Bei deinen Datenbankabfragen schickst du ja in erster Linie (SQL) Strings ab, die der Server dann lokal verarbeitet und dir dann das Ergebenis wieder zurückschickt. Wenn du also deine 9000 Zahlen zusammenzählen möchtest, macht das der Server und nicht deine Programmiersprache.

Ich verwende sehr gerne Python im Zusammenhang mit DBs, da es sehr einfach, klar strukturiert und durch den Interpreter auch sehr interaktiv ist.

Tabellar
Gast

Donnerstag 30. Juni 2005, 15:12

hallo tabelar,

danke für die Antwort... Nein, ich habe das Wort "datenbank" benutzt aber diese Files erzeuge ich alleine... :roll:
Ich mache physikalische Computer Simulationen und die Daten (Ergebnisse) sind enorme Files... Diese muss ich später bearbeiten... je nach dem was ich im Moment brauche oder was für eine Abbildung ich erzeugen will. Sehr often geht es um etwas total Neues

Es geht nur darum, ob python einfach und schnell diese sehr grossen Files behandeln kann oder nicht...

Danke nochmal
BlackJack

Donnerstag 30. Juni 2005, 15:13

Tabellar hat wohl, wie ich auch erst, überlesen, das Du Dateien mit so vielen Einträgen hast. Mein Rat: Schmeiss die erstmal komplett in die Datenbank und folge dann Tabellars Vorschlag SQL für diese einfachen Aufgaben zu benutzen.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 30. Juni 2005, 18:14

Sowas konnte man auch vermutlich gut mit PySQLite abwickeln.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Donnerstag 30. Juni 2005, 21:44

Anonymous hat geschrieben: danke für die Antwort... Nein, ich habe das Wort "datenbank" benutzt aber diese Files erzeuge ich alleine... :roll:
Ich mache physikalische Computer Simulationen und die Daten (Ergebnisse) sind enorme Files... Diese muss ich später bearbeiten... je nach dem was ich im Moment brauche oder was für eine Abbildung ich erzeugen will. Sehr often geht es um etwas total Neues

Es geht nur darum, ob python einfach und schnell diese sehr grossen Files behandeln kann oder nicht...
Grundsätzlich würde ich ja sagen. Python hat nicht mehr oder weniger Probleme mit grossen Dateien als andere vergleichbare Sprachen.

Welches Format haben Deine Daten denn? Reine Textdateien oder ein Binärformat?

Textdateien haben das Problem, das man nicht einfach wahlfrei auf Einträge zugreifen kann, ausser wenn die Zeilen alle exakt gleich lang sind. Das kann man damit umgehen, das man in einem ersten Arbeitsschritt einen Index erstellt, der für jede Zeile die Startposition in der Datei enthält.

Wenn Du die Daten hauptsächlich sequenziell bearbeiten willst, dann würde ich sagen, dass Python wegen seiner `Generator-Functions` sogar gut geeignet ist, weil man damit die Algorithmen so schreiben kann, als wenn man mit einer grossen Liste arbeiten würde, aber immer nur der wirklich benötigte Teil im Speicher sein muss.
Zuletzt geändert von BlackJack am Freitag 1. Juli 2005, 20:42, insgesamt 1-mal geändert.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 30. Juni 2005, 22:21

pau_ hat geschrieben: Typischerweise habe ich Files mit 40 Spalten und bis auf 4 Millionen Zeilen. Ich muss zB 9000 Zahlen von der ersten Spalte auswählen und sie mit einer Zahl multiplizieren und dann ein output File mit ihnen als erste Spalte und sowas derartiges in einer zweiten Spalte erzeugen.
[...]
Welche Sprache wäre am Besten für mich? python? ruby? perl?... fortran??
Hi Pau!

Bei Python bist du goldrichtig :-)

Aus reinem Interesse habe ich mal ein kleines Beispiel programmiert. Dieses Programm erstellt eine Datei mit 2.000.000 Zeilen und 40 Spalten. Diese Datei wird dann durchlaufen und die jeweils erste Spalte mit der Zeilennummer multipliziert. Das Ergebnis wird in eine zweite Datei geschrieben.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import time

DATAFILE = r"C:\_Ablage\filetest\data\myfile.txt"
DESTFILE = r"C:\_Ablage\filetest\data\destfile.txt"


# Eine Datei mit 2.000.000 Zeilen und 40 Spalten erzeugen
print "Datei erzeugen BEGIN"
print "Uhrzeit:", str(time.strftime("%H:%M:%S", time.localtime()))
seconds_begin = time.mktime(time.localtime())
seconds = seconds_begin

f = file(DATAFILE, "w")
for ii in xrange(1, 2000000):
   zeile = ";".join([str(ii)] * 40) + "\n"
   f.write(zeile)
   if not(ii % 500000):
      print "   %s (%s Sekunden)" % \
         (str(ii), str(time.mktime(time.localtime()) - seconds))
      seconds = time.mktime(time.localtime())
f.close()

print "Datei erzeugen END"
print "Uhrzeit:", time.strftime("%H:%M:%S", time.localtime())
print "Dauer in Sekunden:", str(time.mktime(time.localtime()) - seconds_begin)
print


# Die erzeugte Datei durchlaufen und die Zahl der ersten Spalte mit
# einem Zaehler multiplizieren. Diese Zahl wird in eine neue Datei geschrieben.
print "Datei durchlaufen BEGIN"
print "Uhrzeit:", str(time.strftime("%H:%M:%S", time.localtime()))
seconds_begin = time.mktime(time.localtime())
seconds = seconds_begin

dest = file(DESTFILE, "w")

f = file(DATAFILE, "rU")
for linenumber, line in enumerate(f):
   dest.write("%s\n" % (long(line.split(";")[0]) * linenumber))
   if not(linenumber % 500000):
      print "   %s (%s Sekunden)" % \
         (str(linenumber), str(time.mktime(time.localtime()) - seconds))
      seconds = time.mktime(time.localtime())

f.close()
dest.close()

print "Datei durchlaufen END"
print "Uhrzeit:", time.strftime("%H:%M:%S", time.localtime())
print "Dauer in Sekunden:", str(time.mktime(time.localtime()) - seconds_begin)
Der Durchlauf ergab dieses Ergebnis:

Code: Alles auswählen

Datei erzeugen BEGIN
Uhrzeit: 23:11:46
   500000 (10.0 Sekunden)
   1000000 (14.0 Sekunden)
   1500000 (13.0 Sekunden)
Datei erzeugen END
Uhrzeit: 23:12:32
Dauer in Sekunden: 46.0

Datei durchlaufen BEGIN
Uhrzeit: 23:12:32
   0 (0.0 Sekunden)
   500000 (10.0 Sekunden)
   1000000 (9.0 Sekunden)
   1500000 (9.0 Sekunden)
Datei durchlaufen END
Uhrzeit: 23:13:10
Dauer in Sekunden: 38.0
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 30. Juni 2005, 22:37

Nur so eine Anmerkung... Warum berechnest du die Dauer so komisch? Warum nimmst du nicht einfach time.time() ?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 30. Juni 2005, 22:48

jens hat geschrieben:Nur so eine Anmerkung... Warum berechnest du die Dauer so komisch? Warum nimmst du nicht einfach time.time() ?
Hi jens!

Du hast natürlich vollkommen recht. Was man nicht im Kopf hat, hat man in den Fingern :-)

Hier noch mal der Code, diesmal aber mit 4 Mio. Zeilen und mit time.time()

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import time

DATAFILE = r"C:\_Ablage\filetest\data\myfile.txt"
DESTFILE = r"C:\_Ablage\filetest\data\destfile.txt"


# Eine Datei mit 4.000.000 Zeilen und 40 Spalten erzeugen
print "Datei erzeugen BEGIN"
print "Uhrzeit:", str(time.strftime("%H:%M:%S", time.localtime()))
seconds_begin = time.time()
seconds = seconds_begin

f = file(DATAFILE, "w")
for i in xrange(1, 4000000):
   zeile = ";".join([str(i)] * 40) + "\n"
   f.write(zeile)
   if not(i % 500000):
      print "   %s (%s Sekunden)" % (str(ii), str(time.time() - seconds))
      seconds = time.time()
print "   %s (%s Sekunden)" % (str(i), str(time.time() - seconds))
f.close()

print "Datei erzeugen END"
print "Uhrzeit:", time.strftime("%H:%M:%S", time.localtime())
print "Dauer in Sekunden:", str(time.time() - seconds_begin)
print


# Die erzeugte Datei durchlaufen und die Zahl der ersten Spalte mit
# einem Zaehler multiplizieren. Diese Zahl wird in eine neue Datei geschrieben.
print "Datei durchlaufen BEGIN"
print "Uhrzeit:", str(time.strftime("%H:%M:%S", time.localtime()))
seconds_begin = time.time()
seconds = seconds_begin

dest = file(DESTFILE, "w")

f = file(DATAFILE, "rU")
for linenumber, line in enumerate(f):
   dest.write("%s\n" % (long(line.split(";")[0]) * linenumber))
   if not(linenumber % 500000):
      print "   %s (%s Sekunden)" % (str(linenumber), str(time.time() - seconds))
      seconds = time.time()
print "   %s (%s Sekunden)" % (str(linenumber), str(time.time() - seconds))

f.close()
dest.close()

print "Datei durchlaufen END"
print "Uhrzeit:", time.strftime("%H:%M:%S", time.localtime())
print "Dauer in Sekunden:", str(time.time() - seconds_begin)
Das Ergebnis:

Code: Alles auswählen

Datei erzeugen BEGIN
Uhrzeit: 23:37:49
   500000 (9.0 Sekunden)
   1000000 (14.0 Sekunden)
   1500000 (12.0 Sekunden)
   2000000 (11.0 Sekunden)
   2500000 (16.0 Sekunden)
   3000000 (14.0 Sekunden)
   3500000 (14.0 Sekunden)
   3999999 (12.0 Sekunden)
Datei erzeugen END
Uhrzeit: 23:39:31
Dauer in Sekunden: 102.0

Datei durchlaufen BEGIN
Uhrzeit: 23:39:31
   0 (0.0 Sekunden)
   500000 (16.0 Sekunden)
   1000000 (25.0 Sekunden)
   1500000 (20.0 Sekunden)
   2000000 (17.0 Sekunden)
   2500000 (26.0 Sekunden)
   3000000 (23.0 Sekunden)
   3500000 (33.0 Sekunden)
   3999998 (57.0 Sekunden)
Datei durchlaufen END
Uhrzeit: 23:43:08
Dauer in Sekunden: 217.0
Den Performaceeinbruch erkläre ich mir mit den großen Zahlen, die bei dieser Zeilenanzahl zu multiplizieren sind. Ich habe aber keine Lust mehr auszutesten, ob das so stimmt.

Vorsicht! Dieses Beispiel erzeugt eine 1,15 GB große Datei.

mfg
Gerold
:-)
Zuletzt geändert von gerold am Donnerstag 30. Juni 2005, 23:36, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 30. Juni 2005, 23:03

gerold hat geschrieben:Vorsicht! Dieses Beispiel erzeugt eine 1,15 GB große Datei.
Wobei damit dann ehr die Preformance der Festplatte gemessen werden dürfte ;)

Warum machst du eigentlich seconds = seconds_begin ? Und arbeitest nicht generell mit seconds_begin?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 30. Juni 2005, 23:30

jens hat geschrieben: Warum machst du eigentlich seconds = seconds_begin ? Und arbeitest nicht generell mit seconds_begin?
Hi jens!

Das mache ich nur damit die Duisburger über mich her ziehen können :wink: :lol: :D
Nein, im Ernst -- seconds_begin brauche ich um auszurechnen, wie lange der gesamte Vorgang dauerte.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Freitag 1. Juli 2005, 08:07

pau_ hat geschrieben:...Typischerweise habe ich Files mit 40 Spalten und bis auf 4 Millionen Zeilen. Ich muss zB 9000 Zahlen von der ersten Spalte auswählen und sie mit einer Zahl multiplizieren und dann ein output File mit ihnen als erste Spalte und sowas derartiges in einer zweiten Spalte erzeugen...
Hallo pau,

hättest Du uns vielleicht mal die ersten 5 Spalten und 5 Zeilen deiner Ergebnisdatei? Dann wüssten wir mal, um was es geht und was für Zahlen-/Datentypen du verwendest... :roll:

Tabellar
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Freitag 1. Juli 2005, 12:38

Mit anderen Worten, wir sind alle zum Schluss gekommen, dass es mit Python möglich ist.

Irgendwie in einem Python Forum nicht weiter verwunderlich, oder? ;) Aber meine Vorredner haben recht, Python ist gut geeignet für sowas.

@tabellar: Hast jetzt diesen Astronauten-Avatar um dem Astronautenruf gerecht zu werden, oder? :idea:
My god, it's full of CARs! | Leonidasvoice vs Modvoice
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Freitag 1. Juli 2005, 12:46

Leonidas hat geschrieben:@tabellar: Hast jetzt diesen Astronauten-Avatar um dem Astronautenruf gerecht zu werden, oder? :idea:
Ha, ha ... lustig finde ich das ja schon und ne "Tabelle" als Avatar wäre doch eher langweilig, oder? :P

Tabellar

PS:
Ich hab noch ein paar andere Astronauten Avatars im backup...
Gast

Montag 4. Juli 2005, 11:29

Hey!

Danke an alle! Ich habe nicht erwartet, dass die Frage so ausfuehrlich erklaert wuerde... Das ist aber nett von Euch :D

Vor Allem Danke an Gerold... Das war aber ein gutes Beispiel.

Ich habe Beides, ein binary File und damit kann ich das ascii File erzeugen.

Nur als Beispiel hier ist der Anfang eines solchen Files:

Code: Alles auswählen

# 1: rank 2: TTOT 3: N 4: NNB 5: NPAIRS 6: NMERGE 7: MULT 8: NS 9: NSTEPI 10: NSTEPB 11: NSTEPR 12: NSTEPU 13: ERROR 14: BE_3 15: NRUN 16: MODEL 17: TCOMP 18: TRC 19: DMIN1 20: DMIN2 21: DMIN3 22: DMIN4 23: AMIN 24: RMAX 25: RSMIN 26: NEFF 27: RSCALE 28: RTIDE 29: RD 30: RC 31: NC 32: ZMC 33: RHOD 34: RHOM 35: CMAX 36: CNNB 37: COST 38: IUNP 39: NP 40: CMR_4 41: CMRDOT_4 42: AZ 43: EB 44: EM 45: TCR 46: I6 47: NNPRED 48: NBCORR 49: NBFULL 50: NBVOID 51: NRCONV 52: NICONV 53: NBSMIN 54: NBDIS 55: NBDIS2 56: NCMDER 57: NBDER 58: NFAST 59: NBFAST 60: NBLOCK 61: NBPRED 62: NKSTRY 63: NKSREG 64: NKSHYP 65: NKSPER 66: NPRECT 67: NKSREF 68: NKSMOD 69: NTTRY 70: NTRIP 71: NQUAD 72: NCHAIN 73: NMERG 74: NSTEPT 75: NSTEPQ 76: NSTEPC 77: NBLCKR 78: NBFLUX 79: RBAR 80: ZMBAR 81: TIDAL_4 82: RDENS_1 83: RDENS_2 84: RDENS_3 85: TTOToverTCR 86: TSCALE 87: VSTAR 88: VC
  0  0.0000000E+00      10000         40          0          0          0      10000          0          0     0          0  0.00000E+00 -0.25000E+00   1    1  0.16810E+03  0.21792E+00  0.10000E+03  0.10000E+03  0.10000E+03  0.10000E+03  0.10000E+03  0.00000E+00  0.10000E+03        117  0.90060E+00  0.90060E+01  0.11412E+01  0.10441E+00        163  0.12094E-01  0.26877E+02  0.10898E+03  0.34485E+05  0.52342E+02  0.45145E-01          0      0  0.18590E+01  0.39104E-06  0.16832E-01  0.00000E+00  0.00000E+00  0.28293E+01          0          0     0      11442          3          0          0          0          0          0          0          0   0          0          0          0          0          0          0          0          0          0 0          0          0          0          0          0          0          0          0          0          0  0.11000E+01  0.69998E+04  0.00000E+00 -0.78159E+00 -0.19105E+00  0.80924E+00  0.00000E+00  0.00000E+00  0.10001E+05  0.13465E+01
  0  0.5000000E+01      10000         24          0          0          0      10000   20487935      26820   10238535      38147 -0.15731E-06 -0.24991E+00   1    2  0.53939E+05  0.10185E-03  0.15961E-05  0.10000E+03  0.10000E+03  0.10000E+03  0.10000E+03  0.00000E+00  0.10000E+03        117  0.91150E+00  0.91150E+01  0.12583E+01  0.65956E-02          4  0.91112E-01  0.13285E+06  0.19661E+06  0.43179E+05  0.44032E+02  0.91188E-02          0      0  0.18590E+01  0.15471E-04  0.10510E-01  0.00000E+00  0.00000E+00  0.28305E+01          1    1527936    7078589      28512        649    1332976    1558061       4801          0          0     110327          0   0          0    1566710    2064755     299649         46         11          0          0          0 0          0          0          0          0          0          0          0          0    1527930   22929158  0.11000E+01  0.69998E+04  0.00000E+00 -0.86199E+00 -0.26147E+00  0.87861E+00  0.17665E+01  0.10000E+01  0.10001E+05  0.22611E+01
  0  0.1000000E+02       9999         24          0          0          0       9999   41364518      29311   21272759      41755 -0.10274E-05 -0.25012E+00   1    3  0.11328E+06  0.17645E-04  0.14337E-05  0.10000E+03  0.10000E+03  0.10000E+03  0.10000E+03  0.00000E+00  0.10000E+03        117  0.88831E+00  0.88831E+01  0.11756E+01  0.62558E-02          3  0.91048E-01  0.12034E+06  0.17595E+06  0.24925E+05  0.44577E+02  0.83546E-02          0      0  0.18578E+01  0.82768E-04  0.10507E-01  0.00000E+00  0.00000E+00  0.28264E+01          2    3694637   14143866      32292       1274    2733545    3417285       4801          0          0     128935          0   0          0    3774113    4193165     880605         56         11          0          0          0 0          0          0          0          0          0          0          0          0    3694628   44019274  0.11000E+01  0.69998E+04  0.00000E+00 -0.83524E+00 -0.22585E+00  0.79580E+00  0.35381E+01  0.20000E+01  0.10001E+05  0.36180E+01
Die restlichen Zeilen moechte ich nicht posten... das macht ein seehr grosses File (ueber 1 GB) und ich will die Forum Seite nicht belanden :lol:
(die erste Zeile ist nur eine Erklaerung von den verschiedenen Spalten)

Dass das Ganze zu berechnen nur 3,61 Minuten bei Gerold gedauert hat ist beeindruckend. Ich gehe davon aus, dass genau das Gleiche mit gawk zu machen, viel laenger dauern wuerde... :?:

Vielen Dank auf jeden Fall...

Pau
Antworten