View previous topic :: View next topic |
Author |
Message |
schmidicom Veteran
Joined: 09 Mar 2006 Posts: 1970 Location: Schweiz
|
Posted: Tue Mar 19, 2024 3:25 pm Post subject: [solved] PyQt6 und QFile |
|
|
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')) |
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 |
|
|
sMueggli Guru
Joined: 03 Sep 2022 Posts: 495
|
Posted: Tue Mar 19, 2024 4:36 pm Post subject: |
|
|
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 |
|
|
firefly Watchman
Joined: 31 Oct 2002 Posts: 5317
|
|
Back to top |
|
|
schmidicom Veteran
Joined: 09 Mar 2006 Posts: 1970 Location: Schweiz
|
Posted: Tue Mar 19, 2024 6:04 pm Post subject: |
|
|
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 |
|
|
firefly Watchman
Joined: 31 Oct 2002 Posts: 5317
|
Posted: Tue Mar 19, 2024 6:51 pm Post subject: |
|
|
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 |
|
|
schmidicom Veteran
Joined: 09 Mar 2006 Posts: 1970 Location: Schweiz
|
Posted: Tue Mar 19, 2024 7:20 pm Post subject: |
|
|
@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 |
|
|
firefly Watchman
Joined: 31 Oct 2002 Posts: 5317
|
Posted: Tue Mar 19, 2024 7:34 pm Post subject: |
|
|
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 |
|
|
schmidicom Veteran
Joined: 09 Mar 2006 Posts: 1970 Location: Schweiz
|
Posted: Tue Mar 19, 2024 7:38 pm Post subject: |
|
|
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 |
|
|
|