Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
[solved] PyQt6 und QFile
View unanswered posts
View posts from last 24 hours
View posts from last 7 days

 
Reply to topic    Gentoo Forums Forum Index Deutsches Forum (German)
View previous topic :: View next topic  
Author Message
schmidicom
Veteran
Veteran


Joined: 09 Mar 2006
Posts: 1970
Location: Schweiz

PostPosted: Tue Mar 19, 2024 3:25 pm    Post subject: [solved] PyQt6 und QFile Reply with quote

Ja das hier ist zwar ein Forum für Gentoo und nicht Python aber leider wüsste ich nicht wo ich sonst fragen könnte (das "www.python-forum.de" ist mir gelinde gesagt schlicht zu unfreundlich).
Ich bin gerade dabei ein Python-Script zu schreiben und komme beim Umgang mit "QFile" einfach nicht weiter und Google ist mal wieder auch völlig nutzlos.

Hier zwei Beispiele (im selben Verzeichnis ablegen) die das selbe Problem haben:
test.py:
#!/usr/bin/env python3

import os
from PyQt6.QtCore import (
    QDir,
    QFile
)

absolute_path = os.path.dirname(__file__)
print(absolute_path)

QDir.addSearchPath("base", absolute_path)
test_file = QFile("base:text.txt")
print(test_file.exists())

test_file.open(QFile.ReadOnly | QFile.Text)
print(str(test_file.readAll(), 'utf-8'))
text.txt:
TestText


Das ganze endet immer wieder in:
Code:
AttributeError: type object 'QFile' has no attribute 'ReadOnly'

Aber nur mit PyQt6, mit PyQt5 funktioniert der gleiche Code einwandfrei. Was mache ich falsch? Fehlt auf meinem System irgendein Package?
_________________
Lenovo - ThinkPad P16s Gen 2 - 21K9CTO1WW


Last edited by schmidicom on Tue Mar 19, 2024 7:22 pm; edited 1 time in total
Back to top
View user's profile Send private message
sMueggli
Guru
Guru


Joined: 03 Sep 2022
Posts: 495

PostPosted: Tue Mar 19, 2024 4:36 pm    Post subject: Reply with quote

Ich würde dem Compiler glauben. Ich bin zwar kein Qt- oder Python-Entwickler, aber ein Blick in die Dokumentation zeigt auch keinen Hinweis darauf, dass "QFile.ReadOnly" richtig ist (weder bei Qt noch bei PyQt).

Sowas müsste aber gehen:
Code:
test_file.open(QIODevice::ReadOnly | QIODevice::Text)
Back to top
View user's profile Send private message
firefly
Watchman
Watchman


Joined: 31 Oct 2002
Posts: 5317

PostPosted: Tue Mar 19, 2024 4:54 pm    Post subject: Reply with quote

Laut doku kann das nicht funktionieren für Qt6
In Qt5 hat es funktioniert weil QFile von QIODevice ableitet und dort die open modes definiert sind.
Und dadurch auch indirekt via QFile erreichbar sind
Aber selbst dort wird in der Docu die direkte Verwendung von QIODevice.<openmode> beschrieben.
https://doc.qt.io/qtforpython-5/PySide2/QtCore/QFile.html#PySide2.QtCore.PySide2.QtCore.QFile.setFileName

Richtig ist es "QtCore.QIODeviceBase.OpenModeFlag" zu nutzen.
https://doc.qt.io/qtforpython-6/PySide6/QtCore/QFile.html#PySide6.QtCore.PySide6.QtCore.QFile.open
https://doc.qt.io/qtforpython-6/PySide6/QtCore/QIODeviceBase.html#PySide6.QtCore.PySide6.QtCore.QIODeviceBase.OpenModeFlag

In deinem Beispiel
QtCore.QIODeviceBase.ReadOnly und QtCore.QIODeviceBase.Text

Vermutlich wurde auch der code generator angepasst das sowas nicht mehr passiert.
_________________
Ein Ring, sie zu knechten, sie alle zu finden,
Ins Dunkel zu treiben und ewig zu binden
Im Lande Mordor, wo die Schatten drohn.
Back to top
View user's profile Send private message
schmidicom
Veteran
Veteran


Joined: 09 Mar 2006
Posts: 1970
Location: Schweiz

PostPosted: Tue Mar 19, 2024 6:04 pm    Post subject: Reply with quote

Auch so:
Code:
#!/usr/bin/env python3

import os
from PyQt6.QtCore import (
    QDir,
    QFile,
    QIODeviceBase
)

absolute_path = os.path.dirname(__file__)
print(absolute_path)

QDir.addSearchPath("base", absolute_path)
test_file = QFile("base:text.txt")
print(test_file.exists())

test_file.open(QIODeviceBase.ReadOnly)
print(str(test_file.readAll(), 'utf-8'))

ändert sich nicht wirklich etwas.
Code:
AttributeError: type object 'QIODeviceBase' has no attribute 'ReadOnly'


EDIT:
So funktioniert es:
Code:
#!/usr/bin/env python3

import os
from PyQt6.QtCore import (
    QDir,
    QFile,
    QIODeviceBase
)

absolute_path = os.path.dirname(__file__)
print(absolute_path)

QDir.addSearchPath("base", absolute_path)
test_file = QFile("base:text.txt")
print(test_file.exists())

test_file.open(QIODeviceBase.OpenModeFlag.ReadOnly)
print(str(test_file.readAll(), 'utf-8'))

_________________
Lenovo - ThinkPad P16s Gen 2 - 21K9CTO1WW
Back to top
View user's profile Send private message
firefly
Watchman
Watchman


Joined: 31 Oct 2002
Posts: 5317

PostPosted: Tue Mar 19, 2024 6:51 pm    Post subject: Reply with quote

Dann scheinen die Beispiele in der doku nicht für PyQt6 korrekt angepasst worden.
Wobei auch
Quote:
QIODevice.OpenModeFlag.<Mode>
funktioniert. Und das ist auch mit PyQt5 kompatible, falls das relevant sein sollte

EDIT: Hab den Grund für den unterschied gefunden.
In älteren SIP versionen (SIP wird für bauen der Qt python bindings genutzt) wurden enums als ein custom datentyp dargestellt (vergleichbar mit dem enum datentyp in C++ vor C++11),

Vor C++11 stellte der name des enums keinen eigenen scope dar, in dem die enum "werte" nur sichtbar sind.
Sondern die enum "Werte" waren auch in dem scope sichtbar in dem das enum selbst definiert wurde.
Code:
class FooEnum // Vor C++11
{
   public:
      enum Fruits
      {
         Apple,
         Orange
      };
};

FooEnum::Apple // Gültiger Zugriff auf enum Wert
FooEnum::Fruits::Apple // Gültiger Zugriff auf enum Wert


Grund: Erst mit Python 3.4 bekam python selbst support für einen enum datentypen.
Und der python enum type ist ein scoped enum wie in C++11. Und mit PyQt6 wird nur noch der python enum datentyp verwendet.
Code:

class FooScopedEnum // Seit C++11
{
   public:
      enum class Fruits
      {
         Apple,
         Orange
      };
};

FooScopedEnum::Apple // Ungültiger Zugriff
FooScopedEnum::Fruits::Apple // Gültiger Zugriff auf enum Wert

_________________
Ein Ring, sie zu knechten, sie alle zu finden,
Ins Dunkel zu treiben und ewig zu binden
Im Lande Mordor, wo die Schatten drohn.
Back to top
View user's profile Send private message
schmidicom
Veteran
Veteran


Joined: 09 Mar 2006
Posts: 1970
Location: Schweiz

PostPosted: Tue Mar 19, 2024 7:20 pm    Post subject: Reply with quote

@firefly
Kleine Ergänzung: Ich musste "QIODeviceBase", nicht "QIODevice", verwenden damit es funktioniert.

Dieser Mist hat mir heute den ganzen Nachmittag versaut und nervlich gefühlt auch ein oder mehr Jahre Lebenszeit gekostet. Es ist unbeschreiblich frustrierend wenn man ein Beispiel nach dem anderen durchprobiert und jedesmal den selben beschissenen Fehler entgegen geschlagen bekommt. Trotzdem vielen Dank für die Hilfe, letztendlich kam dadurch eine funktionierende Lösung zustande und ich kann mit dem Script weitermachen.

PS: Sollte ich in der Firma jemals wieder auf die Idee kommen für ein scheinbar simples Problem eine kleine Anwendung zu schreiben liefert mich hoffentlich sofort jemand beim Psychologen ab damit mir der diese Schnapsidee wieder ausredet...
_________________
Lenovo - ThinkPad P16s Gen 2 - 21K9CTO1WW


Last edited by schmidicom on Tue Mar 19, 2024 7:37 pm; edited 1 time in total
Back to top
View user's profile Send private message
firefly
Watchman
Watchman


Joined: 31 Oct 2002
Posts: 5317

PostPosted: Tue Mar 19, 2024 7:34 pm    Post subject: Reply with quote

schmidicom wrote:
@firefly
Kleine Ergänzung: Ich musste "QIODeviceBase", nicht "QIODevice", verwenden damit es funktioniert.

Wenn du QIODevice statt QIODeviceBase importierst dann geht es auch damit ;)
Wobei es auch mit QFile geht. Denn QFile ist von QIODevice abgeleitet und QIODevice ist von QIODeviceBase abgeleitet.
Daher ist das Enum OpenModeFlag auch über alle child klassen namen erreichbar.
_________________
Ein Ring, sie zu knechten, sie alle zu finden,
Ins Dunkel zu treiben und ewig zu binden
Im Lande Mordor, wo die Schatten drohn.
Back to top
View user's profile Send private message
schmidicom
Veteran
Veteran


Joined: 09 Mar 2006
Posts: 1970
Location: Schweiz

PostPosted: Tue Mar 19, 2024 7:38 pm    Post subject: Reply with quote

firefly wrote:
schmidicom wrote:
@firefly
Kleine Ergänzung: Ich musste "QIODeviceBase", nicht "QIODevice", verwenden damit es funktioniert.

Wenn du QIODevice statt QIODeviceBase importierst dann geht es auch damit ;)
Wobei es auch mit QFile geht. Denn QFile ist von QIODevice abgeleitet und QIODevice ist von QIODeviceBase abgeleitet.
Daher ist das Enum OpenModeFlag auch über alle child klassen namen erreichbar.

Ich werde es morgen mal ausprobieren.

EDIT:
Ja es funktioniert auch mit QFile aber man muss seit PyQt6 das "OpenModeFlag" dazwischen packen.
Code:
#!/usr/bin/env python3

import os
from PyQt6.QtCore import (
    QDir,
    QFile
)

absolute_path = os.path.dirname(__file__)
print(absolute_path)

QDir.addSearchPath("base", absolute_path)
test_file = QFile("base:text.txt")
print(test_file.exists())

# QFile close the File after readAll automatically
test_file.open(QFile.OpenModeFlag.ReadOnly)
test_content = test_file.readAll()

print(type(test_content))
print(type(test_content.data()))
print(type(test_content.data().decode()))
print(test_content.data().decode())

_________________
Lenovo - ThinkPad P16s Gen 2 - 21K9CTO1WW
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Deutsches Forum (German) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum