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

2018-08-17 16:54:10 +08:00
 iismark2018

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

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

8200 次点击
所在节点    Python
11 条回复
ysc3839
2018-08-17 18:50:51 +08:00
用管道重定向其他进程的 stdout ?
jiangwb
2018-08-17 19:00:44 +08:00
是的,输出重定向就可以了。
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
2018-08-19 11:40:46 +08:00
@Droi 好的,我试试周一的时候,谢谢!
iismark2018
2018-08-20 11:56:14 +08:00
@jiangwb 主要已经做了重定向,在当前的 py 代码里面 print 可以直接打印到文本框里面,但是调用其他的 py 文件,这个 py 文件 print 的信息不会打印。
iismark2018
2018-08-20 11:57:30 +08:00
@Droi 尝试了一下,文本框无法打印想要输出的内容,因为执行的是线程,然后在这个线程下面 用重定向不好使。
iismark2018
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
2018-08-20 15:20:13 +08:00
用 os.system 启动程序。程序输出数据都丢到 sys.stdout。怎么拿出来动态存在一个变量,不太清楚。

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

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

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

按行输出
iismark2018
2018-08-21 11:49:37 +08:00
@frostming fp = os.popen(cmd) rd = fp.readlines() for i in rd: print(i) 我是这样的不实时,感谢大佬 为小弟解了难题,爱你么么!!!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/480792

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX