V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
iismark2018
V2EX  ›  Python

请教一个有关 Python , print 输出信息到 GUI 界面得问题?

  •  
  •   iismark2018 · 2018-08-17 16:54:10 +08:00 · 8405 次点击
    这是一个创建于 2295 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在使用得 PYQT5 做的做了一个 GUI 界面,在这个 GUI.py 文件里面 print 打印得信息已经让我重定向到了文本框中,有一个问题,我在调用其他 py 文件的时候(这个 py 文件也有 print 打印信息),无法打印到 GUI 界面下的文本框中,而是打印到了 pycharm 得控制台,有谁能帮我想想思路怎么做可以?

    我是通过 os.system(“ python +py 文件”) 调用得。

    11 条回复    2018-08-21 11:49:37 +08:00
    ysc3839
        1
    ysc3839  
       2018-08-17 18:50:51 +08:00 via Android
    用管道重定向其他进程的 stdout ?
    jiangwb
        2
    jiangwb  
       2018-08-17 19:00:44 +08:00
    是的,输出重定向就可以了。
    Droi
        3
    Droi  
       2018-08-17 20:04:57 +08:00
    用 QProcess()
    http://doc.qt.io/qt-5/qprocess.html#readAllStandardOutput

    ```python
    p = QProcess()
    p.setProcessChannelMode(QProcess.MergedChannels)
    p.setProcessEnvironment(QProcessEnvironment.systemEnvironment())

    p.readyRead.connect(GUIoutput)
    p.start(“ python +py 文件”, QIODevice.ReadWrite)

    def GUIoutput():
    TextEdit.moveCursor(QTextCursor.End)
    outputTextEdit.insertPlainText(
    str(p.readAllStandardOutput(), "utf-8"))
    TextEdit.moveCursor(QTextCursor.End)
    ```

    具体自己修改下,代码流程是这样的。
    iismark2018
        4
    iismark2018  
    OP
       2018-08-19 11:40:46 +08:00 via iPhone
    @Droi 好的,我试试周一的时候,谢谢!
    iismark2018
        5
    iismark2018  
    OP
       2018-08-20 11:56:14 +08:00
    @jiangwb 主要已经做了重定向,在当前的 py 代码里面 print 可以直接打印到文本框里面,但是调用其他的 py 文件,这个 py 文件 print 的信息不会打印。
    iismark2018
        6
    iismark2018  
    OP
       2018-08-20 11:57:30 +08:00
    @Droi 尝试了一下,文本框无法打印想要输出的内容,因为执行的是线程,然后在这个线程下面 用重定向不好使。
    iismark2018
        7
    iismark2018  
    OP
       2018-08-20 12:01:27 +08:00
    贴一下源码
    import time
    from comm.atc import atLogger, atChat
    import subprocess
    import sys
    import os
    import time
    import datetime
    import requests
    import json
    import random
    from PyQt5.QtWidgets import (QApplication,QWidget,QLabel,QAction,QProgressBar,
    QPushButton,QMainWindow,QTextEdit,QGridLayout,QComboBox)
    from PyQt5.QtGui import QIcon,QTextCursor
    from PyQt5.QtCore import QThread,pyqtSignal,QCoreApplication,QObject,QBasicTimer,Qt,QProcess,QProcessEnvironment,QIODevice
    from comm.at import COMPORT
    class ThreadAp(QThread):
    name = """操作 AP 控制"""
    apstatus = pyqtSignal()
    def run(self):
    # url = "http://192.168.104.1/"
    # s = requests.session()
    # header ={
    # "token":"Ku2vhFFTc9K5V%24Laf2l2V9I%24PqX%249I",
    # "Accept-Encoding": "gzip, deflate",
    # "Accept-Language": "zh-CN, zh;q=0.9",
    # "Referer": "http://192.168.104.1/",
    # "User-Agent":"Mozilla/5.0(Windows NT10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/67.0.3396.62 Safari/537.36",
    # }
    # login = {"method":"do","login":{"password":"0KcgeXhc9TefbwK"}}
    # response = requests.post(url,data=json.dumps(login),headers=header).text
    # jsonload = json.loads(response)
    # stok = jsonload["stok"]
    # print(stok)
    # setwlanurl = "http://192.168.104.1/stok=%s/ds"%stok
    # channelnum = {"method":"set","wireless":{"wlan_host_2g":{"channel":"1", "mode": "3"}}}
    # channelnum2 ={"method":"set","wireless":{"wlan_host_2g":{"channel":"11","mode":"1","bandwidth":"1"}}}
    # channerlpost = requests.post(setwlanurl, data=json.dumps(channelnum))
    # print(channerlpost.text)
    script = os.getcwd() + r'\network\Network_01.py' # 获取当前路径拼接 Network_01 所在位置
    cmd = 'python ' + '-m unittest '+script # python +py 所在地址
    # r = os.system(cmd) # 执行 runTest.py 文件
    r =subprocess.Popen(cmd,shell=True)
    -----------------------------------------------------在这个下面加-------------------------------------------------------------------

    class ThreadQt(QThread):
    name = """AT 命令测试线程"""
    status = pyqtSignal() #实例化一个无参数信号
    steps = pyqtSignal(int) #实例化一个 int 参数信号
    times = 2 #设置测试次数参数

    def run(self):
    for i in range(0, self.times):
    n = i + 1
    print("------------Test Round : %s on %s------------" % (str(n), COMPORT))
    print("--------------------V1.1 测试版------------------")
    print("---------------------" + datetime.datetime.fromtimestamp(time.time()).strftime(
    "%Y-%m-%d-%H-%M-%S") + "------------------")
    time.sleep(0.2)
    script = os.getcwd() + r'\runTest.py' #获取当前路径拼接 runTest 所在位置
    cmd = 'python ' + script #python +py 所在地址
    os.system(cmd) #执行 runTest.py 文件
    time.sleep(1) #休眠 1 秒
    print("-----------------------第%s 遍测试已完成--------------------"%n)
    print("\n")
    step = n*(100/self.times) #计算百分比
    self.steps.emit(step) #发射 step 信号给进度条槽
    try:
    os.system('python '+os.getcwd()+r'\config\SendMail.py')#获取当前路径拼接 SendMail 所在位置
    print("邮件发送成功")
    except:
    print("Error: 无法发送邮件")
    time.sleep(0.5)
    print("*****自动化全部测试完毕,请查看 result 文件下的 Html 报告*****")
    self.status.emit()#发射 step 信号给开始测试 slotStart 槽

    class EmittingStream(QObject):
    textWritten = pyqtSignal(str) #实例化一个 str 参数信号

    def write(self, text):
    self.textWritten.emit(str(text))#发射一个 str 参数信号给 normalOutputWritten 槽

    class MainWindow(QMainWindow):
    name = """主界面"""
    def __init__(self):
    super().__init__()
    self.title = "" #初始化界面工具名称
    self.left = 300
    self.top = 300
    self.width = 750
    self.height = 500
    self.imge = '' #初始化界面工具图标
    self.initUI()

    def initUI(self):
    self.setWindowTitle(self.title) #设置 GUI 界面名称
    self.setGeometry(self.left, self.top, self.width, self.height) #设置 GUI 界面大小
    self.setWindowIcon(QIcon(self.imge)) #设置 GUI 界面图标
    self.textedit = QTextEdit(self) #添加一个 text 文本框
    self.textedit.move(300, 50)
    self.textedit.resize(400, 350)
    self.textedit.setObjectName("textedit") #设置一个 text 文本框名字
    self.textedit.setReadOnly(True) #设置文本框只读模式
    self.settingAction = QAction(QIcon(), '&DUT 串口参数', self) #添加一个菜单栏属性
    self.versionAction = QAction(QIcon(), '&联盛德发布\n'
    'V1.1 测试版', self) #添加一个菜单栏属性
    self.Secondwindow = Secondwindow() #实例化第二个 GUI 界面对象
    self.settingAction.triggered.connect(self.Secondwindow.show) #这是点击串口参数弹出另一个 GUI 界面
    mainMenu = self.menuBar()
    fileMenu = mainMenu.addMenu('设置') #添加一个菜单栏
    viewMenu = mainMenu.addMenu('版本')
    fileMenu.addAction(self.settingAction)
    viewMenu.addAction(self.versionAction)
    self.button = QPushButton('AT 测试', self) #添加一个开始测试按钮
    self.button.move(50, 70)
    self.exitbu = QPushButton('退出', self) #添加一个退出按钮
    self.exitbu.move(90, 350)
    self.button2 = QPushButton('加网测试', self) #添加一个开始测试按钮
    self.button2.move(170, 70)
    self.exitbu.clicked.connect(QCoreApplication.instance().quit) #为退出按钮链接退出快捷功能
    self.thread = ThreadQt() #实例化 ThreadQt 线程对象
    self.threadAP = ThreadAp() #实例化 ThreadAp 线程对象
    self.button.clicked.connect(self.slotStart)
    self.button2.clicked.connect(self.startAp)
    self.thread.status.connect(self.slotEnd)
    self.thread.steps.connect(self.doAction)
    self.threadAP.apstatus.connect(self.endAp)
    self.pbar = QProgressBar(self)
    self.pbar.setGeometry(50, 450, 700, 25) # 从左上角 30-50 的界面,显示一个 200*25 的界面
    self.setWindowFlags(Qt.WindowMinimizeButtonHint) # 禁止最大化
    sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)# 重定向输出
    sys.stderr = EmittingStream(textWritten=self.normalOutputWritten)
    def slotStart(self):
    try:
    os.remove(os.getcwd()+r'\config\time.txt')
    except:
    pass
    self.pbar.setValue(0)
    self.button.setText("自动化测试中")
    self.button.setEnabled(False)
    self.thread.start()

    def slotEnd(self):
    self.button.setText("测试")
    self.button.setEnabled(True)

    def doAction(self,steps):
    self.pbar.setValue(steps)

    def startAp(self):
    self.pbar.setValue(0)
    self.button2.setText("自动化测试中")
    self.button2.setEnabled(False)
    self.threadAP.start()
    # try:
    # self.threadmail.start()
    # except:
    # pass
    def endAp(self):
    self.button2.setText("测试")
    self.button2.setEnabled(True)


    def __del__(self):
    sys.stdout = sys.__stdout__
    sys.stderr = sys.__stderr__

    def normalOutputWritten(self, text):
    cursor = self.textedit.textCursor()
    cursor.movePosition(QTextCursor.End)
    cursor.insertText(text)
    self.textedit.setTextCursor(cursor)
    self.textedit.ensureCursorVisible()
    def main():
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())



    if __name__ == '__main__':
    main()
    Droi
        8
    Droi  
       2018-08-20 15:20:13 +08:00
    用 os.system 启动程序。程序输出数据都丢到 sys.stdout。怎么拿出来动态存在一个变量,不太清楚。

    用 r=subprocess.Popen 可以用 r.communicate()拿数据。

    你可以先写小脚本,再慢慢改。
    iismark2018
        9
    iismark2018  
    OP
       2018-08-20 16:32:05 +08:00
    @Droi 嗯嗯,用 os.popen()获取到内容,我需要 read 一下然后打印出来,这样能实现但是就不是实时同步了,等待测试执行完毕后,可以打印出信息。
    frostming
        10
    frostming  
       2018-08-21 10:45:24 +08:00   ❤️ 1
    @iismark2018 谁说不能实时了?

    fp = os.popen('run script')
    for line in iter(fp.readline, ''):
    print(line, end='')

    按行输出
    iismark2018
        11
    iismark2018  
    OP
       2018-08-21 11:49:37 +08:00
    @frostming fp = os.popen(cmd) rd = fp.readlines() for i in rd: print(i) 我是这样的不实时,感谢大佬 为小弟解了难题,爱你么么!!!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3250 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 13:12 · PVG 21:12 · LAX 05:12 · JFK 08:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.