problem.next(): IOError: Bad file descriptor

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
...
User
Beiträge: 116
Registriert: Mittwoch 23. Dezember 2009, 20:22

Hallo...
Hier kommt dann auch schon mein nächstes Problem.

Ich habe mir mit HTML mal ein paar Templates erstellt.

Platzhalter im Format: <+++Platzhaltername+++> sind dabei eingefügt.

Es besteht ein Dictionary. In den Keys sind die Platzhalternamen, und der zugehörige Wert ist dann der zugewiesene Wert.

das HTML-Dokument sieht beispielsweise so aus:

Code: Alles auswählen

<html>

<head></head>

<body>
   <h1><+++Titel+++></h1>
   <span style="font-size:13pt;"><+++Text+++></span>
</body>

</html> 
Der code sieht so aus:

Code: Alles auswählen

import os


mydict = {'Titel':'Hallo Welt!', 'Text':'Kleines Testprogram'}

for file in os.listdir('.'):
    if 'Template' in file \
    and '.html' in file:
        html = open(file, 'rw')
        content = html.read()
        for key in mydict.key():
            content.replace('<+++' + key + '+++>', mydict[key])
        html.write(content)
        html.close()
Das Problem:
Ich bekomme einen Error: IOError: Bad file descriptor in der Zeile: html.write(content)

Woran könnte das liegen?

lg,
...

EDIT: Die Datei ist richtig geöffnet:
Ich kann mir den content mit Print einfach ausgeben lassen, und alles stimmt.
Lediglich beim Schreiben bekomme ich Probleme...
Wobei es eigenartigerweise einen unterschied macht, ob ich es so wie o.g mache, oder einfach schreibe:

Code: Alles auswählen

file = open('MyTemplate1.html', 'rw')
file.write('blub')
file.close()
Denn letzteres funktioniert einwandfrei!

--------

#Einen Teil habe ich vergessen:
#Die Templates liegen im Ordner Templates.
#Zu beginn Kopiere ich sie mit shutil.copy in das Arbeitsverzeichnis #(derzeit das Verzeichnis '.') - das in welchem auch das Script läuft.
#Allerdings: Nach dem Error ist die Datei noch nicht einmal kopiert!
Stimmt nicht: Ist doch schon da.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Mir fallen da zunächst ein paar Dinge auf:

1.) Wieso ein eigenes Template-Format? Es gibt zig gute Template-Engines (jinja2, mako, usw. - und zur Not auch in der Standard-Lib eine primitive).

2.) Du überschreibst das built-in file. Wieso nimmst Du nicht fname oder filename?

Mit dem "rw"-Modus kenne ich mich nicht aus. Aber darf man denn eine Datei wirklich bis zum Ende einlesen und dann noch schreiben?

Edit: In der Doku habe ich nicht gesehen, dass man zwei Modi mischen darf!
...
User
Beiträge: 116
Registriert: Mittwoch 23. Dezember 2009, 20:22

http://www.python-forum.de/topic-462.html

Das rw kann ich auch weglassen, es ändert sich nichts.
Ich wollte halt die Datei lesen und schreiben...

Wieso ein eigenes Template-Format?
Du hast ja nichtmal gefragt wofür das Template.

http://pypi.python.org/pypi/pisa/3.0.32 benötigt ein Design aus HTML & CSS
Dazu kommt, das ich HTML und CSS zumindest halbwegs beherrsche...
Ebenfalls toll: Ich kann sie gleich ins Web stellen (per FTP), und muss nicht noch extra eine HTML-Seite zusätzlich erstellen.

Die meisten anderen PDF-Generatoren konnte ich nicht installieren... Gab es probleme mit dem Compilieren.
Und dieses Pakte bei dem es mit einer eigenen XML-Sprache beschrieben wird dafür zu lernen, war mir echt eigentlich zu blöd, wenn es doch dieses Lukrativ klingende Angebot gibt...


fname und filename waren mir unbekannt.
Mal sehen was die machen...


lg,
...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

... hat geschrieben:http://www.python-forum.de/topic-462.html

Das rw kann ich auch weglassen, es ändert sich nichts.
Ich wollte halt die Datei lesen und schreiben...
Wo in dem Thread siehst Du da so was? (Zudem ist er sehr alt - die aktuelle Referenz ist da sicher verlässlicher als solch ein Thread)
Wieso ein eigenes Template-Format?
Du hast ja nichtmal gefragt wofür das Template.
Also ist es kein eigenes Template-Format? Dann nehme ich alles zurück. Nur hat mir Dein Link dahingehend nicht geholfen, das zu erkennen ;-)
fname und filename waren mir unbekannt.
Mal sehen was die machen...
Die "machen" nichts, das sollten bessere Namen für die Dateinamen in Deinem Script sein. "file" ist ein schlechter Bezeichner, da es eine built-in Funktion desselben Namens gibt.
...
User
Beiträge: 116
Registriert: Mittwoch 23. Dezember 2009, 20:22

Der Thread den ich dir Zeigte hat nichts mit rw zu tun.
Das rw macht wiegesagt bei mir keinen Unterschied zu garnichts...
Ich habe es jetzt also weggelassen.

In dem Thread wird aber Propagiert, wenn man etwas in einem Textfile (ein HTML-File ist ja im grunde ein Textfile) ändern will - ersetzen will was auch immer, müsse man den ganzen Text einlesen, die Ersetzungen/Einfügungen vornehmen, und dann wieder schreiben.

Im 2. Post wird das mit readlines erledigt.
Ich möchte aber in jeder Zeile jedes vorkommen der Platzhalter ersetzen.
Darum fand ich es simpler, alles in einen String mit Read zu lesen, und dort direkt ersetzen.

Ich habe an meinem Rechner an welchem ich schreibe leider keinen Internetzugang, aus dem grund muss ich hier immer die Scripts neu von hand schreiben.

In wirklichkeit ist das HTML-Dokument Template1.html etwa 400 Zeilen lang (inklusive CSS)

Tatsächlich verwende ich html_file als Namen, nicht file.

Ich hab gehofft, es seien Funktionen, mit denen ich bestimmen kann, das die Datei mit einem anderen Dateinamen gespeichert werden soll...
Das wäre nämlich eine feine Lösung gewesen, auf das ich nicht immer die die Templates erst kopieren muss, sondern direkt öffnen, und wo anders dann speichern...


Das Format HTML ist tatsächlich ein uraltes Format.
Im Web-Bereich dürfte es oft vorkommen, das man Templates für Websiten in HTML schreibt, und den rest mir PHP/Python/Ruby/Pearl/whatsoever ausfüllt... oder den entspechenden Code (PHP) gleich einbettet...

Dazu kommt, das pisa HTML als Templatesprache zum Designen verwendet, und dann mit diesem HTML-Dokument ein PDF schreibt.

Da ich gleichzeitig die Daten auch im Internet einstellen möchte, kommt mir das zusätzlich entgegen.

Als Alternative käme natürlich auch LaTeX in Frage.

lg,
...
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

... hat geschrieben:Ich hab gehofft, es seien Funktionen, mit denen ich bestimmen kann, das die Datei mit einem anderen Dateinamen gespeichert werden soll...
Das wäre nämlich eine feine Lösung gewesen, auf das ich nicht immer die die Templates erst kopieren muss, sondern direkt öffnen, und wo anders dann speichern...
Entweder erklärst du dein Anliegen gerade sehr unglücklich oder du hast den naheliegendsten Ansatz übersehen. Dieser Ansatz bestände darin, direkt in Python zwei Dateien zu verwenden. Die erste Datei enthält das Template und wird nur zum Lesen geöffnet und die zweite Datei braucht nur geschrieben werden und enthält das Ergebnis nach dem Ersetzen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Und dann nutze doch zusätzlich eine fertige Template-Engine! Es gibt eine sehr rudimentäre Funktionalität in der Standard-Lib (Kapitel 8.1.4. Template strings).
...
User
Beiträge: 116
Registriert: Mittwoch 23. Dezember 2009, 20:22

Du meinst:

Code: Alles auswählen

for template_name in os.listdir('.' + os.sep + 'template'):

    template_file = open('.' + os.sep + 'template' + template_name, 'r')
    my_file = open('.' + template_name, 'w')

    content = template_file.read()
    template_file.close()

    for key in mydict.keys():
        content.replace('<+++' + key + '+++>', mydict[key]

    my_file.write(content)
    my_file.close()
Klingt gut!
Werde ich gleich mal ausprobieren!


lg,
...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Bitte noch zusätzlich wenigstens das open mit with angehen - dann sparst Du Dir das Schließen. Ganz auf Nummer sicher gehst Du dann noch mit try... except IOError.
...
User
Beiträge: 116
Registriert: Mittwoch 23. Dezember 2009, 20:22

Wenn ich mit Try arbeite würg ich den Error doch ab, und wenn er mal berechtigter weise auftauchen sollte, so wäre das schade!

with hab ich nie kapiert... hab mich damit aber auch nicht groß auseinandergesetzt...
Es ist mir aber lieber genau zu wissen, wann ich eine Datei schließe, warum, und wesshalb...

btw:
Mit der letzten Version funktioniert es.

Vielen Dank dir /me für deine Idee - damit kann ich mir jetzt auch das Importen von shutil spaaren, und 9 Zeilen.


Auch dir Danke, Hyperion, für deine Mühe!

Vieleicht werden deine Vorschläge in die nächste Version einfließen.


lg,
...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

... hat geschrieben:Wenn ich mit Try arbeite würg ich den Error doch ab, und wenn er mal berechtigter weise auftauchen sollte, so wäre das schade!
Solange Du eine konkrete Exception abfängst ist doch alles ok ;-)
with hab ich nie kapiert... hab mich damit aber auch nicht groß auseinandergesetzt...
Naja, da gibts nicht viel zu wissen denke ich mal.

Code: Alles auswählen

with open() as name:
    # name enthält das file object wie gehabt
    # close ist überflüssig
Es ist mir aber lieber genau zu wissen, wann ich eine Datei schließe, warum, und wesshalb...
Hm... wie Du meinst ;-)
lunar

... hat geschrieben:Es ist mir aber lieber genau zu wissen, wann ich eine Datei schließe, warum, und wesshalb...
Das weißt Du aber eben nicht, wenn Du so vorgehst. Wenn vor dem ".close()" eine Ausnahme geworfen wird, dann wird der ".close()"-Aufruf nicht erreicht, somit ist das Schließen der Datei dem GC überlassen, und der GC ist nicht deterministisch (zumindest nicht nach Dokumentation) … die Datei wird einfach irgendwann geschlossen, oder vielleicht auch gar nicht.

Nur wenn Du "with" oder ein "try: … finally: …"-Konstrukt nutzt, weißt Du wirklich, wann eine Datei geschlossen wird.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Am "weshalb" aendert sich ebenfalls nichts, geschlossen wird, wenn es eine Ausnahme gibt oder der Block verlassen wird. Gut, bis auf die Tatsache, dass die Ressource sauber geschlossen wird im Falle von Ausnahmen.

Zu den Ausnahmen: Es heisst nicht umsonst Ausnahmebehandlung. Wenn eine auftritt weiss der Programmierer (bei den meisten) genau, was querschlaegt und kann entsprechend reagieren ohne, dass das Programm terminieren muss.
...
User
Beiträge: 116
Registriert: Mittwoch 23. Dezember 2009, 20:22

Ich sehe schon: Ich hab noch viel zu lernen, junger padawan...


Also sollte ich die Exception abfangen, und dann den Fehler nur ausgeben?

Wenn ich jetzt folgendes schreibe:

Code: Alles auswählen

try:
    foo = open(bar)
except IOError:
    print 'ja was denn'
Wie kann ich an das was eigentlich zusammen mit dem Programmabbruch ausgegeben wird rankommen?
Also das ich den Original-Fehlertext dann ausgebe, statt nur 'ja was denn' oder einer alternativen statischen Ausgabe?


lg,
...
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Ein `raise` ohne Angabe einer Ausnahme wirft die letzte Ausnahme erneut.
Benutzeravatar
Masaru
User
Beiträge: 425
Registriert: Mittwoch 4. August 2004, 22:17

Du kannst tun und lassen was Du Dir so vorstellst für Dein Programm.

Un wenn es nach einem 3x-maligen Versuch ein subprocess call mit "format c:" und der "Y" Bestätigung ist.
Deiner Kreativität ist da keine Grenze gesetzt.

Aber nur so als Tipp ;), Du bist ja ein Computer-User, hast also folglich schon einige Programme benutzt und in Aktion gesehen - ebenso deren Fehlerverhalten. Orientier Dich einfach am besten an dem, was Dir selber am besten gefallen hat.

Wenn Du 10 Personen nach "Fehlerbebandlung und -Management" fragen würdest, bekämest Du vermutlich 11 verschiedene Antworten.

>>Masasru<<
...
User
Beiträge: 116
Registriert: Mittwoch 23. Dezember 2009, 20:22

Das heist, ich kann guten mutes einfach alle Fehler abfangen?

Code: Alles auswählen

while 1:
    try:
        print str(muh)[10]
    except KeybordInterrupt:
        print 'Raus hier!'
        break
    except:
        raise
        muh += 1
Das ist schön!


Ich fand die Bluescreens immer toll...
Oder diese Lösung: http://www.geekherocomic.com/2009/06/03 ... orkaround/
Benutzeravatar
Masaru
User
Beiträge: 425
Registriert: Mittwoch 4. August 2004, 22:17

Sicher kannst Du alle Fehler abfangen.

Nur solltest Du Dir folgenden Gedanken machen: "Wenn ich alle Fehler abfange ... wie stelle ich dann fest, dass es einen Fehler gab?"

Solange Du einen Weg findest, diese Frage zu lösen ... bist Du auf dem richtigen Weg.

>>Masaru<<
...
User
Beiträge: 116
Registriert: Mittwoch 23. Dezember 2009, 20:22

Das ist ne gute Frage...
Wenn ich sie einfach nur mit Raise ausgebe, gehen sie verloren.


Mal sehen, ob logging noch funktioniert, wenn ich die exceptions abfange...
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ist die Diskussion eigentlich schon an der Stelle angekommen, wo Zeile 13 aus dem ursprünglichen Codeschnipsel nicht funktioniert? Immer daran denken: Strings in Python sind unveränderlich. Das `replace` erzeugt einen neuen String, der aber sofort wieder vergessen wird. Das kann nicht funktionieren.

Stefan
Antworten