【问题标题】:Python + Pyside + QThreads emit signal and segmentation faultPython + Pyside + QThreads 发出信号和分段错误
【发布时间】:2023-08-25 23:01:01
【问题描述】:

您好,我是 python 和 PySide 的新手,经过数小时的研究,我尝试开发一个简单的 GUI 来显示来自 API 服务的一些数据。

我的程序很“简单”,我实现了 Qthread,并有工作线程向 api 发出请求,并以 QObject 作为参数向主线程发出信号。

主线程接收信号并更新GUI。

问题是我运行程序时出现分段错误错误。

在实现 api 请求之前,我尝试简单地将数字作为字符串传递并完美运行。

我认为我的错误出现在我的主线程尝试访问 GObject 并且我的工作线程也尝试访问该对象时。

这是我的代码:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
from PySide import QtGui
from PySide import QtCore
import urllib2
import json
import datetime
import time
from termcolor import colored
from blessings import Terminal


class MySig(QtCore.QObject):
    sig = QtCore.Signal(QtCore.QObject)

class MyThread(QtCore.QThread):

    def __init__(self, parent=None):
        QtCore.QThread.__init__(self, parent)
        self.exiting = 10
        self.signal = MySig()


    def callAping(self, jsonrpc_req):
        url = "https://api.betfair.com/exchange/betting/json-rpc/v1"
        headers = { 'X-Application' : '***********', 'X-Authentication' : '**************************' ,'content-type' : 'application/json' }
        try:
            req = urllib2.Request(url, jsonrpc_req, headers)
            response = urllib2.urlopen(req)
            jsonResponse = response.read()
            return jsonResponse
        except urllib2.URLError:
            print 'Oops no service available at ' + str(url)
            exit()
        except urllib2.HTTPError:
            print 'Oops not a valid operation from the service ' + str(url)
            exit()

    def getMarketBookBestOffers(self):

        marketId = "1.116260985"
        market_book_req = '{"jsonrpc": "2.0", "method": "SportsAPING/v1.0/listMarketBook", "params": {"marketIds":["' + marketId + '"],"priceProjection":{"priceData":["EX_BEST_OFFERS"]}}, "id": 1}'
        """
        print  market_book_req
        """
        market_book_response = self.callAping(market_book_req)
        """
        print market_book_response
        """
        market_book_loads = json.loads(market_book_response)
        try:
            market_book_result = market_book_loads['result']
            return market_book_result
        except:
            print  'Exception from API-NG' + str(market_book_result['error'])
            exit()


    def run(self):
        while True:
            market_book_result = self.getMarketBookBestOffers()
            self.signal.sig.emit(market_book_result)
            time.sleep(0.5)


class Example(QtGui.QWidget):

    def __init__(self):
        super(Example, self).__init__()
        self.initUI()


    def initUI(self):

        self.selid1 = QtGui.QLabel('id', self)
        self.price11 = QtGui.QLabel('0.0', self)
        self.price12 = QtGui.QLabel('0.0', self)

        self.hbox1=QtGui.QHBoxLayout()
        self.hbox1.addWidget(self.selid1)
        self.hbox1.addWidget(self.price11)
        self.hbox1.addWidget(self.price12)

        self.selid2 = QtGui.QLabel('id', self)
        self.price21 = QtGui.QLabel('0.0', self)
        self.price22 = QtGui.QLabel('0.0', self)

        self.hbox2=QtGui.QHBoxLayout()
        self.hbox2.addWidget(self.selid2)
        self.hbox2.addWidget(self.price21)
        self.hbox2.addWidget(self.price22)

        self.selid3 = QtGui.QLabel('id', self)
        self.price31 = QtGui.QLabel('0.0', self)
        self.price32 = QtGui.QLabel('0.0', self)

        self.hbox3=QtGui.QHBoxLayout()
        self.hbox3.addWidget(self.selid3)
        self.hbox3.addWidget(self.price31)
        self.hbox3.addWidget(self.price32)

        self.vbox=QtGui.QVBoxLayout()
        self.vbox.addLayout(self.hbox1)
        self.vbox.addLayout(self.hbox2)
        self.vbox.addLayout(self.hbox3)

        self.setLayout(self.vbox)

        self.setGeometry(300, 300, 400, 250)
        self.setWindowTitle('Absolute')

        self.thread = MyThread()
        self.thread.start()
        self.thread.signal.sig.connect(self.changelabel)

    def changelabel(self, datas):       
        if(datas is not None):
            for marketBook in datas:
                runners = marketBook['runners']
                if (runners[0]['status'] == 'ACTIVE'):
                    self.selid1.setText(runners[0]['status'])
                    self.price11.setText(str(runners[0]['ex']['availableToBack'][0]['price']))
                    self.price12.setText(str(runners[0]['ex']['availableToLay'][0]['price']))
                else:
                    self.selid1.setText(runners[0]['status'])

                if (runners[1]['status'] == 'ACTIVE'):
                    self.selid2.setText(runners[1]['status'])
                    self.price21.setText(str(runners[1]['ex']['availableToBack'][0]['price']))
                    self.price22.setText(str(runners[1]['ex']['availableToLay'][0]['price']))
                else:
                    self.selid2.setText(runners[1]['status'])

                if (runners[2]['status'] == 'ACTIVE'):
                    self.selid3.setText(runners[2]['status'])
                    self.price31.setText(str(runners[2]['ex']['availableToBack'][0]['price']))
                    self.price32.setText(str(runners[2]['ex']['availableToLay'][0]['price']))
                else:
                    self.selid3.setText(runners[2]['status'])


def main():

    app = QtGui.QApplication(sys.argv)
    ex = Example()
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

对不起我的英语

【问题讨论】:

    标签: python multithreading pyside signals-slots qthread


    【解决方案1】:

    您不需要MySig 类,并且不应将信号定义为发出QObject,因为这与您发出的对象类型不匹配。

    我无法测试您的示例代码,但试试这个:

    class MyThread(QtCore.QThread):
        sig = QtCore.Signal(object)
    
        def __init__(self, parent=None):
            QtCore.QThread.__init__(self, parent)
            self.exiting = 10
        ...
    
        def run(self):
            ...
            self.sig.emit(market_book_result)
        ...
    
    class Example(QtGui.QWidget):
        ...
        def initUI(self):    
            ...
            self.thread = MyThread()
            self.thread.sig.connect(self.changelabel)
            self.thread.start()
    

    【讨论】:

    • 您好,谢谢,这解决了我的问题。但问题出在哪里?当我尝试声明我的信号时?如果我在连接信号之前启动线程,这是错误的吗?我会失去一些发射信号吗?再次感谢
    • @asa。我认为问题在于信号的声明(即使用QObject 而不是object)。但是您可以轻松地测试每种可能性以确保。