英文:
How to correctly type-hint a function with `pyqtSlot()` decorator inside `QRunnable` class?
问题
状态:
- 我正在学习如何在
PyQt库中使用并发/线程,教程来源于www.pythonguis.com。以下是该教程中的简化/部分代码。 - 我希望在我的代码中使用严格的类型提示。但是我在这段代码中使用
mypy时遇到了错误消息(在第二个源代码块中显示)。
问题:
- 在使用
pyqtSlot()装饰器时,如何正确地为函数添加类型提示? - 在这种情况下,
Superclass(返回None)和Subclass(返回str|None)分别是什么?
我尝试解决的问题:
- 我对错误消息感到不满意,这让我很困扰。我浪费了太多时间来解决一行代码的问题。我在互联网上找不到有用的信息。
- 定义(或者说
stub文件)中说pyqtSlot()是这样的:
def pyqtSlot(*types, name: typing.Optional[str] = ..., result: typing.Optional[str] = ...) -> typing.Callable[..., typing.Optional[str]]: ...,由于我对装饰器没有经验,我无法解释这个定义。 stub文件:QtCore.pyi中说Class QRunnable的run方法是这样的:def run(self) -> None: ...。
from typing import Callable
from PyQt5.QtCore import QObject, QRunnable, pyqtSignal, pyqtSlot
import traceback
import sys
class WorkerSignal(QObject):
finished = pyqtSignal()
error = pyqtSignal(tuple)
result = pyqtSignal(object)
progress = pyqtSignal(int)
class Worker(QRunnable):
def __init__(self, fn: Callable[[], str]) -> None:
super(Worker, self).__init__()
self.fn: Callable[[], str] = fn
self.signals: WorkerSignal = WorkerSignal()
@pyqtSlot()
def run(self) -> None: # <====================== 这一行
try:
result: str = self.fn()
except Exception:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
else:
self.signals.result.emit(result)
finally:
self.signals.finished.emit()
$ mypy /tmp/tmp.py
/tmp/tmp.py:22: error: Signature of "run" incompatible with supertype "QRunnable" [override]
/tmp/tmp.py:22: note: Superclass:
/tmp/tmp.py:22: note: def run(self) -> None
/tmp/tmp.py:22: note: Subclass:
/tmp/tmp.py:22: note: str | None
Found 1 error in 1 file (checked 1 source file)
编辑:
-
以下猜测是否正确?
pyqtSlot()接受返回类型为typing.Optional[str](即str | None)的函数。也许这是subclass?QRunnable的run()方法只返回None,也许这是superclass?- 在这种情况下,正确的问题应该是:如果
装饰器的返回值和函数的返回值不同,如何使用装饰器?这个问题是否正确?
英文:
Status:
- I'm learning how to use concurrency/threads within
PyQtlibrary from here www.pythonguis.com. Below is the simplified/part of code from this tutorial. - I want strict type hinting in my code. And I'm getting error messages on this code from
mypy. (Shown on the 2-nd source-code block).
Question:
- How to correctly type-hint the function while using
pyqtSlot()decorator? - What is
Superclass(that returnNone), and what isSubclass(that returnsstr|None) in this case?
What I tried to solve:
- My autistic ass doesn't sit well with error is showing on my text-editor. And I wasted too much time to solve single line. I couldn't find anything useful on the internet.
- The definition (or should I say
stubfile) sayspyqtSlot()is:
def pyqtSlot(*types, name: typing.Optional[str] = ..., result: typing.Optional[str] = ...) -> typing.Callable[..., typing.Optional[str]]: ..., I'm unable to interpret this due to no-experience on decorators. stubfile:QtCore.pyisays thatClass QRunnable'srunis:def run(self) -> None: ....
from typing import Callable
from PyQt5.QtCore import QObject, QRunnable, pyqtSignal, pyqtSlot
import traceback
import sys
class WorkerSignal(QObject):
finished = pyqtSignal()
error = pyqtSignal(tuple)
result = pyqtSignal(object)
progress = pyqtSignal(int)
class Worker(QRunnable):
def __init__(self, fn: Callable[[], str]) -> None:
super(Worker, self).__init__()
self.fn:Callable[[], str] = fn
self.signals: WorkerSignal = WorkerSignal()
@pyqtSlot()
def run(self) -> None: # <====================== this line
try:
result: str = self.fn()
except Exception:
traceback.print_exc()
exctype, value = sys.exc_info()[:2]
self.signals.error.emit((exctype, value, traceback.format_exc()))
else:
self.signals.result.emit(result)
finally:
self.signals.finished.emit()
$ mypy /tmp/tmp.py
/tmp/tmp.py:22: error: Signature of "run" incompatible with supertype "QRunnable" [override]
/tmp/tmp.py:22: note: Superclass:
/tmp/tmp.py:22: note: def run(self) -> None
/tmp/tmp.py:22: note: Subclass:
/tmp/tmp.py:22: note: str | None
Found 1 error in 1 file (checked 1 source file)
EDIT:
-
Is the following guess correct?
pyqtSlot()takes function that returnstyping.Optional[str](i.e.str | None). Perhaps its thesubclass?QRunnable's methodrun()only returnNone, Perhaps it's thesuperclass?- In this case, correct question would be: How to use decorator, if
decorator's returnandfunction's returnare different? Would this be the correct question?
答案1
得分: 2
除了类型提示之外,你不应该在QRunnable方法中使用pyqtSlot。
pyqtSlot装饰器仅用于继承自QObject的类的方法,而QRunnable不是。我已经查阅了几个教程,它们采用了这种不好的做法,因为它并没有带来任何好处。
英文:
Other than the typehint you should not use pyqtSlot in a QRunnable method.
The pyqtSlot decorator is only used in methods of classes that inherit from QObject and QRunnable is not. I have reviewed several tutorials that resort to this bad practice since it does not bring any benefit.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论