Seite 1 von 2
Ergebnis in Datei schreiben
Verfasst: Samstag 6. März 2010, 00:18
von Chibi
Hi, ich hab folgenen Code
Code: Alles auswählen
...
def get_clusters(node, cutoff, parent_is_cluster):
if node.is_leaf():
return
avg=get_average_length(node)
sum_dist = sum(avg)
if node.edge.length is not None:
sum_dist -= get_num_leaf_nodes(node, 0)*node.edge.length
real_dist = sum_dist/get_num_leaf_nodes(node, 0)
if real_dist <= cutoff and not parent_is_cluster:
print ""
print real_dist
print taxon_names(node)
elif real_dist > cutoff:
for n in node.child_nodes():
get_clusters(n, cutoff, False)
cutoff=float(raw_input("Enter Cutoff value: "))
get_clusters(t1.seed_node, cutoff, False)
Und wenn ich das in einer IDE laufen lassen, kann ich den Cutoff Wert eintragen und bekomme ein Ergebnis angezeigt.
Wenn ich jedoch versuche, dass in eine Datei schreiben zulassen kommt nur eine leere Datei raus.
Ich habs damit probiert
Code: Alles auswählen
outfile=open("Ausgabe.txt","w")
outfile.write(get_clusters(t1.seed_node, cutoff, False))
outfile.close()
Aber das geht nicht, ich denke das ist ganz einfach, bin aber grad n bischen doof

Hab sonst auch nur print Anweisungen, in eine Datei schreiben lassen und das ging ganz problemlos
Wenn mir da mal jemand auf die Sprünge helfen könnte, wäre ich sehr dankbar.
Verfasst: Samstag 6. März 2010, 00:28
von derdon
Die Funktion get_clusters gibt None zurück. Du schreibst None in das Dateiobjekt outfile. Was soll da also drin stehen? print schreibt per default in sys.stdout; nicht in die Datei, die es erraten soll. Entweder du gibst der Funktion ein weiteres Argument (das Dateiobjekt) oder du schreibst sie als Generator (Stichwort yield). Letzteres ist um einiges besser, weil get_clusters mit input/output überhaupt nichts zu tun hat.
Verfasst: Samstag 6. März 2010, 00:33
von Chibi
Ah ok, hättest du da mal ein Beispielcode? So sagt mir das grad nichts. Bin noch nicht so erfahren
Edit: So hab mir das mal versucht anzuschauen mit Generatoren, aber ich werd nicht schlau daraus.
Und wie gebe ich der Funktion ein weiters Argument mit, in dem das Ergebnis drinsteht?
Sry, aber ich stell mich wahrscheinlich grad voll blöd an
Verfasst: Samstag 6. März 2010, 00:51
von EyDu
Hallo.
Vielleicht hilft dier
das hier.
Sebastian
Verfasst: Samstag 6. März 2010, 01:03
von Chibi
Jo, vielen Dank schonmal, hatte selbst schonmal gegoogled und mir dazu was durchgelesen, aber ich checks leider nicht richtig. Ich will doch nur den Funktionsaufruf in eine Datei schreiben, das muss man doch einfacher lösen können

Verfasst: Samstag 6. März 2010, 01:17
von derdon
Hier noch ein Beispiel mit nem Generator:
Code: Alles auswählen
>>> def dummy_generator(a,b,c):
... for _ in xrange(10):
... yield (a, b, c)
...
>>> list(dummy_generator(1,2,3))
[(1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3)]
>>> print '\n'.join(map(str, dummy_generator('hallo','welt','alles klar?')))
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
Verfasst: Samstag 6. März 2010, 01:25
von Chibi
Echt, vielen lieben Dank für die Mühe, aber ich versteh nicht, wie mir das helfen kann, ich sehs einfach nicht.
Verfasst: Samstag 6. März 2010, 01:38
von Hyperion
Na, Du willst doch bestimmte Werte, die innerhalb der Funtkion bestimmt werden speichern. Also muss Du quasi dort, wo Du im Moment die Werte printest, diese...
a.) ... entweder dort in eine Datei speichern (File Objekt an die Funktion übergeben)
b.) ... die Werte in eine Datenstruktur packen, die Du jeder Rekursionsstufe übergibst (wie das File Objekt), aber diese auch ganz am Schluss zurückgibst, damit Du diese nach Abschluss sämtlicher Arbeiten an einen Namen binden kanns:
Code: Alles auswählen
result = foo(...)
for value in result:
# tue was mit den einzelnen Werten
c.) wie schon erwähnt anstelle der direkten Verarbeitung in der Funktion an jeder Stelle, an der etwas berechnet wird das ganze per yield zurücklieferst. Durch die Rekursion wird es ein wenig schwerer hier, da Du dann noch in der for-Schleife die Ergebnisse der Rekursionen yielden müßtest. Also etwa so:
Code: Alles auswählen
for value in get_clusters(n, cutoff, False):
yield value
Verfasst: Samstag 6. März 2010, 11:46
von sma
Generatoren sind viel zu umständlich hier. Warum nicht einfach so?
Code: Alles auswählen
def hello(name, f=None):
print >>f, "Hallo %s" % name
# Variante 1, Konsole
hello("Stefan")
# Variante 2, Datei
with open("hello.txt", "w") as f:
hello("Stefan", f)
Stefan
Verfasst: Samstag 6. März 2010, 11:55
von Dav1d
Wieso nicht einfach ein return in der Funktion
Code: Alles auswählen
def hello(name):
return "Hallo %s" % name
# Variante 1, Konsole
print hello("Dav1d")
# Variante 2, Datei
with open("hello.txt", "w") as f:
f.write(hello("Dav1d"))
Verfasst: Samstag 6. März 2010, 11:58
von sma
Weil erstens der OP mehrere Ausgaben macht und zweitens es immer besser ist, zu streamen und nicht erst einen komplexen String zu konstruieren. Es ging mir um eine minimale Änderung des Programms ohne die Logik komplett zu ändern.
Stefan
Verfasst: Samstag 6. März 2010, 12:00
von Dav1d
Wie wäre es mit "writelines" und einer Liste?
Verfasst: Samstag 6. März 2010, 12:08
von Hyperion
Dav1d hat geschrieben:Wie wäre es mit "writelines" und einer Liste?
Auch da wird eine Datenstruktur aufgebaut. Ist also bei einer großen Anzahl von Werten suboptimal. Nuja, hatte es ja auch erst als Möglichkeit (b) aufgeührt

Verfasst: Samstag 6. März 2010, 12:11
von Dav1d
Dann bleibt eigentlich nur noch die Idee von sma (fileobj übergeben) oder yield
Verfasst: Samstag 6. März 2010, 12:14
von Hyperion
Dav1d hat geschrieben:Dann bleibt eigentlich nur noch die Idee von sma (fileobj übergeben) oder yield
Nichts gegen sma, aber das war meine Idee (a)

yield ist hier imho aufgrund der Rekursion nicht wirklich toll, da Du deswegen nicht direkt an die ursprünglich aufrufende Stelle yielden kannst. (Daher auch Idee (c)

)
Verfasst: Samstag 6. März 2010, 13:43
von Chibi
Ok, meint ihr das so? (Ich denke eher nicht, denn das klappt leider nicht.)
Code: Alles auswählen
def get_clusters(node, cutoff, parent_is_cluster):
if node.is_leaf():
return
avg=get_average_length(node)
sum_dist = sum(avg)
if node.edge.length is not None:
sum_dist -= get_num_leaf_nodes(node, 0)*node.edge.length
real_dist = sum_dist/get_num_leaf_nodes(node, 0)
if real_dist <= cutoff and not parent_is_cluster:
yield ""
yield real_dist
yield taxon_names(node)
elif real_dist > cutoff:
for n in node.child_nodes():
get_clusters(n, cutoff, False)
cutoff=float(raw_input("Enter Cutoff value: "))
get_clusters(t1.seed_node, cutoff, False)
for value in get_clusters(n, cutoff, False):
yield value
Mhh, ich bin in dem Punkt grad n bischen doof, könntet ihr mir das an meinem Code zeigen. Ich verzeifel so langsam
P.S.Achso, ich benutze Python 2.5, also das with statement würde nicht gehen
Verfasst: Samstag 6. März 2010, 13:50
von Hyperion
Chibi hat geschrieben:
Mhh, ich bin in dem Punkt grad n bischen doof, könntet ihr mir das an meinem Code zeigen. Ich verzeifel so langsam
Wieso beharrst Du so auf den Generatoen? sma hat Dir doch sogar ein Code Snippet gezeigt, wie man ein File Objekt an eine Funktion übergibt und Werte dort reinschreibt!
Chibi hat geschrieben:
P.S.Achso, ich benutze Python 2.5, also das with statement würde nicht gehen
Man kann natürlich auch auf with verzichten und mit einem geeigneten try...except...finally Konstrukt arbeiten - aber with ist einfacher

Verfasst: Samstag 6. März 2010, 13:51
von DasIch
@Hyperion Du hast ein _statement vergessen

``from __future__ import with_statement``
Verfasst: Samstag 6. März 2010, 14:01
von snafu
@derdon:
Deine `dummy_generator`-Beispiele lassen sich auch so schreiben:
Code: Alles auswählen
>>> from itertools import repeat
>>> list(repeat((1,2,3), 10))
[(1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3), (1, 2, 3)]
>>> for tpl in repeat(('hallo','welt','alles klar?'), 10): print tpl
...
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
('hallo', 'welt', 'alles klar?')
In Python 3.x geht dann zum Glück auch:
Code: Alles auswählen
>>> from functools import partial
>>> ten_times = partial(repeat, times=10)
>>> list(ten_times('bla'))
['bla', 'bla', 'bla', 'bla', 'bla', 'bla', 'bla', 'bla', 'bla', 'bla']
Verfasst: Samstag 6. März 2010, 14:16
von Hyperion
DasIch hat geschrieben:@Hyperion Du hast ein _statement vergessen

``from __future__ import with_statement``
Schande über mich
