如何访问GUI输出?

时间:2014-10-20 18:03:51

标签: python user-interface python-multithreading qtgui qtcore

我正在开发一个测试平台,它通过python gui运行多个测试并打印输出如下。

A Passed
B Passed
C Passed
D Passed
E Passed

只有当A,B,C,D,E全部通过时,gui的按钮才能更改为'Passed'。如果这些测试中的任何一个失败,则应该说失败了。从屏幕上打印的gui访问此输出的方法是什么。

我的测试代码是:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys, os, time
from PyQt4 import QtGui, QtCore
from progress.bar import Bar
import datetime 
import thread

class MyTestBench(QDialog, QtGui.QWidget):
    def __init__(self):
        super(QDialog, self).__init__()
        self.setWindowTitle("Implementation")

        self.progressbar = QtGui.QProgressBar()
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(100)
        self.run_test_button = QtGui.QPushButton('Run Your Tests')
        self.run_test_button.clicked.connect(self.run_test_event)

    def run_test_event(self):
        thread.start_new_thread(self.run_the_test, ("Thread-1", 0.5))
        thread.start_new_thread(self.run_the_progress, ("Thread-2", 0.5))


    def run_the_test(self, tname, delay):        
        os.system("python nxptest.py my_testlist.txt")
        self.progressbar.setValue(100)
        if self.progressbar.value() == self.progressbar.maximum(): 
            time.sleep(3)
            self.run_test_button.setText('Run Your Tests')


    def run_the_progress(self, tname, delay):
        count = 0
        while count < 5:
            self.run_test_button.setText('Running.')
            time.sleep(0.5)
            self.run_test_button.setText('Running..')
            time.sleep(0.5)
            self.run_test_button.setText('Running...')
            value = self.progressbar.value() + 10
            self.progressbar.setValue(value)
            time.sleep(0.5)
            if self.progressbar.value() == self.progressbar.maximum():
                self.progressbar.reset()
            count = count + 1

app = QApplication(sys.argv)
dialog = MyTestBench()
dialog.setGeometry(100, 100, 200, 50)
dialog.show()
app.exec_()

我面临的主要挑战是我是gui编程的新手,我不知道如何访问屏幕上打印的输出。

2 个答案:

答案 0 :(得分:1)

如果您尝试获取某个程序的文本输出,则无法使用os.system运行该程序。正如the docs for that function所说:

  

subprocess模块提供了更强大的工具来生成新流程并检索其结果;使用该模块比使用此功能更可取。有关一些有用的配方,请参阅Replacing Older Functions with the subprocess Module文档中的subprocess部分。

如果您按照这些链接,他们将展示如何做您想做的事情。但基本上,它是这样的:

output = subprocess.check_output(["python", "nxptest.py", "my_testlist.txt"])

如果您使用的是2.6或更早版本,那么您将无法获得check_output;您可以阅读文档以了解如何在communicate之上自行构建文档,或者您可以从PyPI安装subprocess32反向端口并使用它。


来自评论:

  

这有效,但我唯一担心的是在实际打印A Passed B Passed等之前打印的测试有很多结果。我正在寻找一种方法来获取字符串的这部分而不是整个输出。

这是不可能的。你的程序怎么能知道输出的哪一部分是&#34;这部分字符串&#34;哪个部分是&#34;很多结果......在&#34;?

之前打印

如果您可以通过某种方式编辑正在测试的程序,例如,让他们打印他们的&#34;真实&#34;输出到标准输出,但他们的&#34;额外&#34;输出到stderr,或提供一个命令行参数,使它们跳过所有额外的东西 - 这很棒。但假设你不能,除了过滤结果之外别无选择。

但这看起来并不难。如果&#34;真实的每一行&#34;输出为"X Passed""X Failed",其他内容均不以"X "开头(其中X是任何大写的ASCII字母),只是:

test_results = {}
for line in output.splitlines():
    if line[0] in string.ascii_uppercase and line[1] == ' ':
        test_results[line[0]] = line[2:]

现在,最后,你得到了:

{'A': 'Passed', 'B': 'Passed', 'C': 'Passed', 'D': 'Passed', 'E': 'Passed'}

如果你想验证所有的A-E都已被覆盖并且它们全部通过了:

passed = (set(test_results) == set('ABCDE') and
          all(value == 'Passed' for value in test_results.values()))

当然,你可以建立更好的东西,以显示哪些被跳过或没有通过或其他什么。但老实说,如果你想要更强大的东西,你应该使用现有的单元测试框架,而不是从头开始构建一个。

答案 1 :(得分:0)

您可以通过如下队列屏蔽打印输出:

class FileQ(Queue.Queue):
    def __init__(self):
        Queue.Queue.__init__(self)

    def write(self,data):
        self.put(data)

class MyTestBench(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.incoming = FileQ()
        self.setWindowTitle("Implementation")
        sys.stdout = self.incoming
        self.time = QtCore.QTimer()
        self.time.timeout.connect(self.refresh)
        self.time.start(10)
        self.t = QtGui.QTextEdit(self)
        self.t.setObjectName('TextOut')
        self.box = QtGui.QHBoxLayout(self)
        self.setLayout(self.box)
        self.box.addWidget(self.t)
        self.run_test_event()
        self.progressbar = QtGui.QProgressBar(self)
        self.progressbar.setObjectName('BarOut')
        self.box.addWidget(self.progressbar)

    def run_test_event(self):
        thread.start_new_thread(self.run_the_test, ("Thread-1", 0.5))

    def run_the_test(self,*args):
        for i in range(10):
            print i
            time.sleep(1)

    def refresh(self):        
        try:
            data = self.incoming.get_nowait()
        except:
            return
        if data:
            self.t.insertPlainText(str(data))
            self.progressbar.setValue(int(data)*10)