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 :oops:

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? :cry:

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 :oops:

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 :-D

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) :-D )

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

Code: Alles auswählen

from __future__ import with
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 ;-)