Textdatei in QTextEdit einlesen - Programm stürzt ab

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
PythonMarlem
User
Beiträge: 90
Registriert: Dienstag 19. Mai 2020, 19:17
Wohnort: Dußlingen
Kontaktdaten:

Hallo,

ich entwickle einen Texteditor mit Python Qt,

Code: Alles auswählen

# **** Editor zum Datei laden ************
        self.texteditor = QTextEdit('')
        self.layout().addWidget(editormenu)
        self.setCentralWidget(self.texteditor)
mit folgendem Code versuche ich eine Textdatei in QTextEdit einlesen:

Code: Alles auswählen

 def MenuOffnen():
            name = QFileDialog.getOpenFileName(self, 'Datei öffnen')
            with open(open(name, 'r')) as file:
                with file:
                    dateiinhalt = file.read()
                    self.texteditor.setText(dateiinhalt)
Beim ausführen der funktion MenuOffnen() stürzt das ganze Programm ab.
Wie muß der Code aussehen, damit ausgewählte Textdatei in QTextEdit eingelesen wird?
Sirius3
User
Beiträge: 18264
Registriert: Sonntag 21. Oktober 2012, 17:20

Lies doch einfach in der Dokumentation nach, wie man with und open benutzt.
Benutzeravatar
__blackjack__
User
Beiträge: 14027
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@PythonMarlem: Ähm sehr offensichtlich anders. Was hast Du denn da versucht? Was denkst Du denn was `name` ist? Überprüf das mal was Du da vermutest.

Was erwartet die `open()`-Funktion als Argument? Gibt sie zurück? Was erwartet die `open()`-Funktion als Argument? (Nein, das ist kein versehen, dass ich das zweimal geschrieben habe.)

Welche Kodierung hat die Textdatei? Was passiert wenn sie eine andere hat? Was sollte dann passieren?

Wenn Du einen Texteditor schreibst, möchtest Du vielleicht auch die Dateiendezeichen genau so bekommen wie sie in der Datei stehen und nach dem laden schauen *welche* da stehen und sich das merken bevor die gegebenenfalls auf "\n" geändert werden. Und man sollte auch irgendwie damit umgehen können wenn die nicht einheitlich sind.

Mal davon abgesehen das `name` kein (Datei)name ist: Wenn er das wäre, geht der Code auch nicht korrekt mit der Situation um, dass der Benutzer den Dateiauswahldialog abbrechen kann *ohne eine Datei auszuwählen*.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
PythonMarlem
User
Beiträge: 90
Registriert: Dienstag 19. Mai 2020, 19:17
Wohnort: Dußlingen
Kontaktdaten:

es liegt nicht an with!

Dieser Code ist aus einem Tutorial im Internet in dem erklärt wird, wie man mit Python Qt einen Texteditor entwickelt
und der Code bringt das Programm auch zum Absturz:

Code: Alles auswählen

def file_open(self):
        name = QtGui.QFileDialog.getOpenFileName(self, 'Open File')
        file = open(name,'r')

        self.editor()

        with file:
            text = file.read()
            self.textEdit.setText(text)

Benutzeravatar
__blackjack__
User
Beiträge: 14027
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@PythonMarlem: Der Code ist halt falsch. Zum einen weil `name` nicht der Dateiname ist — lass Dir das doch einfach mal ausgeben!

Und dann wird ``with`` falsch verwendet. Zwischen dem öffnen der Datei und dem ``with`` darf kein Code stehen, jedenfalls keiner der auf die Nase fallen kann, denn dann wird die Datei nicht wieder geschlossen.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
PythonMarlem
User
Beiträge: 90
Registriert: Dienstag 19. Mai 2020, 19:17
Wohnort: Dußlingen
Kontaktdaten:

Okay, da wäre ich nie darauf gekommen, dass das Tutorial falschen code veröffentlicht.

Ich habe ihn umgeschrieben:

Code: Alles auswählen

        def MenuOffnen():
            name = QFileDialog.getOpenFileName(self, 'Open File')
            print(name[0])
            file = open(name[0], 'r')

            with file:
                text = file.read()
                self.textEdit.setText(text)
Stürzt aber wieder ab ...
PythonMarlem
User
Beiträge: 90
Registriert: Dienstag 19. Mai 2020, 19:17
Wohnort: Dußlingen
Kontaktdaten:

Das funktioniert:

Code: Alles auswählen

        def MenuOffnen():
            dateiname = QFileDialog.getOpenFileName(self, 'Open File')
            dateiname = dateiname[0]
            dateininhalt = open(dateiname).readlines()
            print(dateininhalt)
Das stürzt ab:

Code: Alles auswählen

        def MenuOffnen():
            dateiname = QFileDialog.getOpenFileName(self, 'Open File')
            dateiname = dateiname[0]
            dateininhalt = open(dateiname).readlines()
            self.texteditor.setText(dateininhalt)
Hat jemand eine Idee warum?
Benutzeravatar
__blackjack__
User
Beiträge: 14027
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@PythonMarlem: Was erwartet denn `setText()` als Argument? Und was übergibst Du da?
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
PythonMarlem
User
Beiträge: 90
Registriert: Dienstag 19. Mai 2020, 19:17
Wohnort: Dußlingen
Kontaktdaten:

ich habe ein array und settext ist ein String.

Ich habe das hier probiert, funktioniert aber auch nicht:

Code: Alles auswählen

        def MenuOffnen():
            dateiname = QFileDialog.getOpenFileName(self, 'Open File')
            dateiname = dateiname[0]
            dateininhalt = open(dateiname).readlines()
            for i in dateininhalt:
                self.texteditor.append(dateininhalt[i])

__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst doch nicht einfach Methodennamen erfinden, und denken, das geht dann alles.

Du hast eine Methode die erlaubt nur das setzen von EINEM String. Und du hast ein Dateiobjekt, und darauf rufst du eine ungeeignete Methode auf, welche dir eine Liste von Dateien zurueckgibt.

Was waere, wenn du mal nachschaust, was es noch so fuer Methoden auf einem Dateiobjekt gibt, die den Inhalt als String zurueckgeben? Denn schliesslich ist das auch was da drin ist. Spoiler: es faengt mit r an.
PythonMarlem
User
Beiträge: 90
Registriert: Dienstag 19. Mai 2020, 19:17
Wohnort: Dußlingen
Kontaktdaten:

Was waere, wenn du mal nachschaust, was es noch so fuer Methoden auf einem Dateiobjekt gibt, die den Inhalt als String zurueckgeben?
Weil ich genau das nicht gefunden habe, bin ich auf die Idee mit der For-Schleife gekommen.
PythonMarlem
User
Beiträge: 90
Registriert: Dienstag 19. Mai 2020, 19:17
Wohnort: Dußlingen
Kontaktdaten:

Ich habe es!

Code: Alles auswählen

 def MenuOffnen():
            dateiname = QFileDialog.getOpenFileName(self, 'Open File')
            dateiname = dateiname[0]
            dateininhalt = open(dateiname).readlines().__str__()
            self.texteditor.setText(dateininhalt)
Sieht irgendwie doch nicht nach der richtigen lösung aus
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

🤦‍♂️

read. Einfach nur read.
Sirius3
User
Beiträge: 18264
Registriert: Sonntag 21. Oktober 2012, 17:20

@PythonMarlem: das ist doch alles nur geraten, statt dass Du mal die Dokumentation von Python liest!

Code: Alles auswählen

def menu_oeffnen(self):
    filename, _ = QFileDialog.getOpenFileName(self, 'Open File')
    if not filename:
        # cancel
        return
    with open(filename, encoding="utf8") as text:
        self.texteditor.setText(text.read())
PythonMarlem
User
Beiträge: 90
Registriert: Dienstag 19. Mai 2020, 19:17
Wohnort: Dußlingen
Kontaktdaten:

Hallo,

habe die Funktion getestet.
Programm stürzt ab mit folgenden Fehlern:
File "C:/Projekte/Python/PQT-Texteditor/PQTTexteditor.py", line 51, in menu_oeffnen
self.texteditor.setText(text.read())
AttributeError: 'MainWindow' object has no attribute 'texteditor'
ich habe inzwischen eine Lösung hinbekommen:

Code: Alles auswählen

  def menuoffnen():
            dateiname = QFileDialog.getOpenFileName(self, 'Datei öffnen', '', 'Textdateien (*.txt)')
            dateiname = os.path.abspath(dateiname[0])
            programmeinstellungen.pfadgeoeffnetedatei = dateiname
            dateininhalt = ''.join(open(dateiname, encoding="utf8").readlines())
            self.texteditor.setText(dateininhalt)
            self.setWindowTitle(os.path.basename(dateiname) + " - Marlems PQTTexteditor")
            self.statusBar().showMessage(programmeinstellungen.pfadgeoeffnetedatei)
Der Grund warum ich trotzdem obige Lösung getestet habe:
Wenn ich mit meiner Lösung Textdateien öffnen die eine große Dateigröße haben, stürzt das Programm ab.
Zuletzt geändert von PythonMarlem am Sonntag 21. Juni 2020, 10:02, insgesamt 1-mal geändert.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Statt deinem gejoine kannst du auch gleich read benutzen. Wie jetzt schon mehrfach angemerkt. Und wenn es mit obigem Code klappt aber nicht dem von Sirius3, dann ist da was anderes im Argen.
Sirius3
User
Beiträge: 18264
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Fehlermeldung kann nicht sein, denn bei deiner "Lösung" benutzt Du auch `texteditor`. Erst mühselig die Datei in Teilen aufzuspalten um sie im selben Schritt wieder in einen String zusammenzupappen statt direkt dem String zu lesen, ändert daran nichts.
Dass menu_oeffnen kein self-Attribut hat, sieht falsch aus, Du hast also irgenetwas komisches in dem Code, den du nicht teilst.
PythonMarlem
User
Beiträge: 90
Registriert: Dienstag 19. Mai 2020, 19:17
Wohnort: Dußlingen
Kontaktdaten:

Ich habe den Tipp bekommen, dass wenn man ein Python-Programm außerhalb der IDE startet, man detailliertere Fehlermeldungen bekommt.

Wenn ich diesen Code im Dosfenster teste:

Code: Alles auswählen

        def menuoffnen():
            dateiname = QFileDialog.getOpenFileName(self, 'Datei öffnen', '', 'Textdateien (*.txt)')
            dateiname = os.path.abspath(dateiname[0])
            programmeinstellungen.pfadgeoeffnetedatei = dateiname
            dateininhalt = ''.join(open(dateiname, encoding="utf8").readlines())
            self.texteditor.setPlainText(dateininhalt)
            self.setWindowTitle(os.path.basename(dateiname) + " - Marlems PQTTexteditor")
            self.statusBar().showMessage(programmeinstellungen.pfadgeoeffnetedatei)
Bekomme ich folgende Fehlermeldung:
QMainWindowLayout::addItem: Please use the public QMainWindow API instead
Traceback (most recent call last):
File "C:/Projekte/Python/PQT-Texteditor/PQTTexteditor.py", line 39, in menuoffnen
dateininhalt = ''.join(open(dateiname, encoding="utf8").readlines())
File "C:\ProgramData\Anaconda3\lib\codecs.py", line 322, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf6 in position 1: invalid start byte
Ohne encoding:

Code: Alles auswählen

        def menuoffnen():
            dateiname = QFileDialog.getOpenFileName(self, 'Datei öffnen', '', 'Textdateien (*.txt)')
            dateiname = os.path.abspath(dateiname[0])
            programmeinstellungen.pfadgeoeffnetedatei = dateiname
            dateininhalt = ''.join(open(dateiname).readlines())
            self.texteditor.setPlainText(dateininhalt)
            self.setWindowTitle(os.path.basename(dateiname) + " - Marlems PQTTexteditor")
            self.statusBar().showMessage(programmeinstellungen.pfadgeoeffnetedatei)
Bekomme ich keine Fehlermeldung.

Was soll ich tun?
Sirius3
User
Beiträge: 18264
Registriert: Sonntag 21. Oktober 2012, 17:20

Dann ist der Text in der Datei nicht UTF8 kodiert, und Du mußt das richtige Encoding angeben.
Kein Encoding anzugeben, kann eben nur zufällig richtig sein. Heutzutage sollte man aber kein anderes Encoding als utf8 mehr benutzen.
getOpenFileName liefert keinen Dateinamen, das ist falsch, daher auch das Tupleunpacking:

Code: Alles auswählen

dateiname, _ = QFileDialog.getOpenFileName(self, 'Datei öffnen', '', 'Textdateien (*.txt)')
Und wie oft soll man hier noch schreiben, dass das readlines mit join kompletter Unfug ist und dass man Dateien mit dem with-Statement öffnet, damit sie auch wieder geschlossen werden.

Code: Alles auswählen

with open(dateiname, encoding="DAS RICHTIGE ENCODING") as input:
    dateiinhalt = input.read()
Benutzeravatar
__blackjack__
User
Beiträge: 14027
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Und wenn man die richtige Kodierung nicht kennt, weil der Benutzer mit einem allgemeinen Texteditor ja beliebige Daten öffnen kann, sogar welche die gar keine Textdateien sind, muss das Programm grundsätzlich mit dieser Situation umgehen können. Also beispielsweise den Benutzer fragen in welcher Kodierung die Datei geöffnet werden soll. Und dann muss man sich die Kodierung auch grundsätzlich merken, denn wenn der Text wieder gespeichert werden soll, braucht man die ja wieder.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten