Seite 1 von 1

Sesam öffne dich

Verfasst: Dienstag 14. April 2015, 18:10
von Sophus
Hallo Leute,

ich bin beim Öffnen einer normalen Text-Datei etwas verwirrt. Hier zunächst mein Code.

Code: Alles auswählen

    def read_licence(self):
        licence_file = None
        setting_folder = unicode(os.path.abspath(os.path.join('licences', 'Licence GPL2.txt')), "UTF-8")
        try:
            licence_file = open(setting_folder).read()
            self.ui_pp_about.textEditLicence.setText(licence_file)
            print("\n\nRead licence-file from: " + setting_folder)
        except (IOError, ValueError):
            QMessageBox.information(None, 'ERROR', licence_file.errorString())
            print "An I/O error or a ValueError occurred"
        except:
            print "An unexpected error occurred"
            raise
        finally:
            if licence_file is not None:
               licence_file.close()
Wie wir sehen, möchte ich eine Text-Datei öffnen, und diesen Inhalt auf das QWidget namens textEditLicence "übertragen". Eine Frage vorweg: Wie ihr im finally-Block seht, versuche ich die Datei immer zu schließen. Jedoch wirft Python die Fehlermeldung:
File "D:\Dan\Python\project_xarphus\files\modules_ui\ui_pp_about.py", line 115, in read_licence
licence_file.close()
AttributeError: 'str' object has no attribute 'close'
Schließt Python denn nach dem Lesen (read()) die Datei selbst, oder muss ich mich als Programmierer selbst darum kümmern?

Re: Sesam öffne dich

Verfasst: Dienstag 14. April 2015, 18:15
von BlackJack
@Sophus: `licence_file` müsstest Du schon an eine *Datei* binden (Typ `file`) und nicht an den Inhalt (Typ `str`). Der übliche Weg ist aber sowieso die ``with``-Anweisung dafür zu verwenden.

Wenn man es schon mit `finally` macht dann ist das mit `None` und dem Test auch unnötig. Man würde einfach *vor* dem ``try`` die Datei öffnen und das Datei-Objekt an einen Namen binden, dann kan man auch sicher sein dass das Objekt im ``finally``-Zweig existiert.

Re: Sesam öffne dich

Verfasst: Dienstag 14. April 2015, 18:30
von Sophus
@BlackJack: Ich habe mir mal deine Anmerkung zum Thema with-Anweisung zur Herzen genommen und es wie folgt umgesetzt.

Code: Alles auswählen

        setting_folder = unicode(os.path.abspath(os.path.join('licences', 'Licence GPL2.txt')), "UTF-8")
        try:
            with open(setting_folder) as f:
                        licence_gpl2 = f.read()
                        self.ui_pp_about.textEditLicence.setText(licence_gpl2)
            print("\n\nRead licence-file from: " + setting_folder)
        except (IOError, ValueError):
            print "An I/O error or a ValueError occurred"
        except:
            print "An unexpected error occurred"
            raise
Wie du siehst, habe ich den finally-Block weggelassen. Kann ich durch die with-Anweisung trotzdem sicher sein, dass die Datei jedesmal geschlossen wird? Ich möchte mit dem Arbeiten der Dateien auf eine Nummer sicher gehen, und nach möglichst alle Maßnahmen ergreifen, damit die Datei nicht durch irgendwelche Fehler geöffnet oder gar zerstört wird.

Re: Sesam öffne dich

Verfasst: Dienstag 14. April 2015, 19:20
von jerch
Sophus hat geschrieben:...Kann ich durch die with-Anweisung trotzdem sicher sein, dass die Datei jedesmal geschlossen wird?...
Darüber kann das Python-Tutorial/Doku Aufschluss geben - https://docs.python.org/2/tutorial/inpu ... le-objects

Re: Sesam öffne dich

Verfasst: Dienstag 14. April 2015, 19:45
von Sirius3
@Sophus: es ist übrigens unsinnig, einen Dateinamen utf-8 dekodieren zu wollen. Entweder abspath liefert schon Unicode, dann ist es unnötig, oder abspath liefert den Dateinamen als Bytes, dann erwartet aber auch open Bytes und im schlimmsten Fall in einem anderen Encoding als utf-8.

Re: Sesam öffne dich

Verfasst: Dienstag 14. April 2015, 20:07
von Sophus
Danke jerch und Sirius3, wird gleich umgesetzt.

@Sirius3: Ich bin nur davon ausgegangen, dass es Probleme geben könnte, wenn im Pfad bestimmte Zeichen enthalten sind, die außerhalb des ASCII-Wertes liegt, zum Beispiel Umlaute etc. Aber wenn abspath dies schon erleidigt, um so besser :-)

Edit: Wenn ich dich richtig verstanden habe, brauche ich die Dekodierung 'utf-8' nicht anzugeben, aber den Pfad weiterhin als unicode() soll ich weiterhin beibehalten, wenn ich mir unangenehme Fehler ersparen will?

Etwa so:

Code: Alles auswählen

        setting_folder = unicode(os.path.abspath(os.path.join('licences', 'Licence GPL2.txt')))

Re: Sesam öffne dich

Verfasst: Mittwoch 15. April 2015, 00:04
von cofi
Da du Python 2 zu benutzen scheinst ist `unicode(x)` aequivalent zu `unicode(x, 'ascii')`. Mit anderen Worten: Es wird eher zusaetzliche Fehler produzieren.

Du kannst Bytes/str nur dann zu unicode dekodieren, wenn du das Encoding kennst. Einfach UTF-8 zu benutzen ist keine gute Idee. Noch dazu ist es AFAIK nur bei moderneren Linux Systemen das Default-Encoding. Windows benutzt beispielsweise UTF-16.

Re: Sesam öffne dich

Verfasst: Mittwoch 15. April 2015, 07:06
von Sirius3
@Sophus: wie schon geschrieben, macht ein unicode nichts besser.

@cofi: Windows benutzt UCS2. Da das noch seltener zu Problemen führt als die leidliche 8bit-Kodierungsdiskussion, ist es noch schwieriger Leuten die Probleme deutlich zu machen, auf die sie damit stoßen können.

Re: Sesam öffne dich

Verfasst: Mittwoch 15. April 2015, 10:27
von jerch
@Sirius3:
Um genau zu sein, nutzt Windows seit Windows 2000 UTF-16 LE mit Unterstützung für surrogate pairs für wchar_t. Betrifft quasi alle `....W()` Funktionen der WinAPI.