python - 无法包装 QWebView.load 方法

标签 python pyqt pyqt4 python-sip

我相信包装函数调用是常见的做法(至少对我来说是这样)。

举个例子,一个简约的包装函数看起来像:

def wrap(fn, *args, **kwargs):
    return fn(*args, **kwargs)

你可以通过

调用任意方法
wrap(qt_method, 1, 2, foo='bar')

相当于直接调用

qt_method(1,2, foo='bar')

这通常对我有用。但是,我遇到了一个没有的情况。

QWebView.load() 似乎不喜欢将空字典扩展到其调用签名中。例如。 wrap(my_webview.load, QUrl('http://istonyabbottstillprimeminister.com')) 失败,异常: TypeError: QWebView.load(QUrl): argument 1 has unexpected type 'QUrl'

下面是一个简单的工作示例,它演示了哪些东西可以工作,哪些不可以。我还没有找到另一种无法像这样包装的 Qt 方法。

import sys
from PyQt4 import QtCore
from PyQt4 import QtGui
from PyQt4.QtWebKit import QWebView

qapplication = QtGui.QApplication(sys.argv)

webview = QWebView()

url = QtCore.QUrl('http://istonyabbottstillprimeminister.com')

# basic wrapping function
def wraps(fn, *args, **kwargs):
    return fn(*args, **kwargs)

args = ()
kwargs = {}

wraps(webview.load, url)     # Doesn't work
webview.load(url, **kwargs)  # Doesn't work
webview.load(url)            # works
webview.url(*args, **kwargs) # works

webview.show()
qapplication.exec_()

当您将 QWebView 子类化并像这样覆盖 load 方法时,也会出现此问题:

def load(self *args, **kwargs):
    return QWebView.load(self, *args, **kwargs)

当然,如果您改为调用 QWebView.load(self, *args) 或不在方法签名中使用 *args, **kwargs,那么您不要得到异常(遵循从上面的简约工作示例中看到的内容)

任何对此的见解都将不胜感激。

最佳答案

除非使用具有特定调用签名组合的重载 PyQt 方法,否则我无法重现这一点。只有当一个签名只有一个参数,而另一个签名只有一个参数并且其余关键字参数具有默认值时,这个错误似乎会被击中。

PyQt4 中正好有九个这样的方法:

QtNetwork
  QSslSocket
    addDefaultCaCertificates(QString, QSsl.EncodingFormat format=QSsl.Pem, QRegExp.PatternSyntax syntax=QRegExp.FixedString)
    addDefaultCaCertificates(list-of-QSslCertificate)

    addCaCertificates(QString, QSsl.EncodingFormat format=QSsl.Pem, QRegExp.PatternSyntax syntax=QRegExp.FixedString)
    addCaCertificates(list-of-QSslCertificate)

    setPrivateKey(QSslKey)
    setPrivateKey(QString, QSsl.KeyAlgorithm algorithm=QSsl.Rsa, QSsl.EncodingFormat format=QSsl.Pem, QByteArray passPhrase=QByteArray())

    setLocalCertificate(QSslCertificate)
    setLocalCertificate(QString, QSsl.EncodingFormat format=QSsl.Pem)

QtWebKit
  QWebFrame
    load(QUrl)
    load(QNetworkRequest, QNetworkAccessManager.Operation operation=QNetworkAccessManager.GetOperation, QByteArray body=QByteArray())

  QGraphicsWebView
    load(QUrl)
    load(QNetworkRequest, QNetworkAccessManager.Operation operation=QNetworkAccessManager.GetOperation, QByteArray body=QByteArray())

  QWebView
    load(QUrl)
    load(QNetworkRequest, QNetworkAccessManager.Operation operation=QNetworkAccessManager.GetOperation, QByteArray body=QByteArray())

QtGui
  QGraphicsScene
    items(Qt.SortOrder)
    QGraphicsScene.items(QPointF)
    QGraphicsScene.items(QRectF, Qt.ItemSelectionMode mode=Qt.IntersectsItemShape)
    QGraphicsScene.items(QPolygonF, Qt.ItemSelectionMode mode=Qt.IntersectsItemShape)
    QGraphicsScene.items(QPainterPath, Qt.ItemSelectionMode mode=Qt.IntersectsItemShape)

  QGraphicsView
    items(QPoint)
    QGraphicsView.items(QRect, Qt.ItemSelectionMode mode=Qt.IntersectsItemShape)
    QGraphicsView.items(QPolygon, Qt.ItemSelectionMode mode=Qt.IntersectsItemShape)
    QGraphicsView.items(QPainterPath, Qt.ItemSelectionMode mode=Qt.IntersectsItemShape)

而你刚好碰上了一个。我会将此报告为针对 SIP 的错误。它用于确定要调用哪个方法的启发式方法总体上看起来非常好,而它恰好只是针对这个特定的组合或调用签名而失败。如果您想最大程度地相信,当输入可能无法很好地解析其参数的任意函数时,事情不会中断,我会使用类似这样的代码:

def call_method_considerately(method, *args, **kwargs):
    if args and kwargs:
        return method(*args, **kwargs)
    elif args:
        return method(*args)
    elif kwargs:
        return method(**kwargs)
    else:
        return method()

关于python - 无法包装 QWebView.load 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28402234/

相关文章:

python - 用 bottle.py 读取 POST 正文

python - Blender Python `bpy` `__init__.py` ,显然是从不存在的模块 `_bpy` 导入的

python - 在 pyqt4 中的特定小部件(透明标签)上覆盖文本

python - 限制qgraphicitem的可移动区域

python - 哪种编码?

python - 组合重新标记 re.IGNORECASE、re.MULTILINE 和 re.DOTALL

python - 在布局内的小部件内循环小部件

python - QT QFileSystemWatcher

python - 将 16 位灰度转换为 QImage

ubuntu - PyQt4 的核心转储