You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt6中通过QProcess获取pagekite.py的Shell输出异常问题

问题:QProcess调用pagekite.py获取的输出与Shell运行不一致,无法更新进度条

问题背景

我用PyQt6开发程序,期望基于pagekite.py的输出来更新进度条。目前用QProcess调用该脚本并编写了输出处理函数,但直接在Shell中运行pagekite.py时输出的是友好提示信息,通过QProcess获取的stdout却是结构化日志格式,与预期不符。

输出对比

Shell运行输出

>>> Hello! This is pagekite.py v1.5.2.201011.                   [CTRL+C = Stop]
Connecting to front-end relay 00.00.000.00:000 ...
 - Relay supports 10 protocols on 23 public ports.
 - Raw TCP/IP (HTTP proxied) kites are available.
 - To enable more logging, add option: --logfile=/path/to/logfile

~<> Flying localhost:80 as https://test.pagekite.me/
<< pagekite.py [exiting] Good-bye!

### QProcess获取的stdout输出
> ```
ts=63837a93; t=2022-11-27T14:56:19; ll=7; connect=000.000.00.000:000

ts=63837a94; t=2022-11-27T14:56:20; ll=8; FE=000.000.00.000:000; err=Rejected; proto=http; reason=quota; domain=test.pagekite.me; id=s2
ts=63837a94; t=2022-11-27T14:56:20; ll=9; FE=000.000.00.000:000; ports=79,80,443, ...; protocols=http,http2,http3,https,websocket,irc,finger,httpfinger,raw; raw_ports=virtual

ts=63837a94; t=2022-11-27T14:56:20; ll=a; wrote=484; wbps=114; read=992; eof=1; id=s2

ts=63837a9e; t=2022-11-27T14:56:30; ll=b; FE=000.000.00.000:000; http_ping_ms=693; win=2; uuid=222cf21b34cfd5bed67bace00000d00000dafff0; unbiased_ms=643

ts=63837ab9; t=2022-11-27T14:56:57; ll=c; FE=000.000.00.000:000; http_ping_ms=693; win=2; uuid=222cf21b34cfd5bed67bace00000d00000dafff0; unbiased_ms=64

程序代码

import time
import sys
from PyQt6.QtCore import QThread, QProcess
from PyQt6.QtWidgets import (
    QApplication,
    QDialog,
    QDialogButtonBox,
    QFormLayout,
    QLineEdit,
    QVBoxLayout,
    QPushButton,
    QLabel,
    QProgressBar,
)

class ProgressBar(QProgressBar):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMaximum(100)
        self._active = False
        self.setTextVisible(False)

    def setBar(self, i):
        self.setValue(i)

    def changeColor(self, color):
        css = """
            ::chunk {{
                background: {0};
            }}
        """.format(color)
        self.setStyleSheet(css)

class Window(QDialog):
    def __init__(self):
        super().__init__(parent=None)
        self.setWindowTitle("QDialog")

        dialogLayout = QVBoxLayout()
        formLayout = QFormLayout()
        confBtn = QPushButton('Configurações')
        self.ligarBtn = QPushButton('Iniciar o aplicativo')
        statusLbl = QLabel('Desligado')
        self.ligado = False
        formLayout.addRow(confBtn)
        formLayout.addRow(self.ligarBtn)
        formLayout.addRow("Status: ", statusLbl)
        dialogLayout.addLayout(formLayout)
        self.connBar = ProgressBar()
        self.connBar.setBar(4)
        self.connBar.changeColor('gray')
        buttons = QDialogButtonBox()
        buttons.addButton('Fechar', QDialogButtonBox.ButtonRole.ActionRole)
        dialogLayout.addWidget(self.connBar)
        self.ligarBtn.clicked.connect(self.iniciaPageKite)
        self.setLayout(dialogLayout)
        self.show()
        y, x = self.geometry().height(), self.geometry().width()
        self.setFixedSize(x, y)
    
    def iniciaPageKite(self):
        self.prcs = QProcess()
        self.prcs.start('py', ['-2.7', 'pagekite.py', '80', 'test.pagekite.me'])
        self.prcs.readyReadStandardOutput.connect(self.pgktOutputHandler)
        self.prcs.readyReadStandardOutput.connect(self.pgktErrorHandler)

    def defPrgBarPrg(self, val):
        self.connBar.setBar(val)

    def defPrgBarClr(self, clr):
        self.connBar.changeColor(clr)

    def pgktOutputHandler(self):
        res = self.prcs.readAllStandardOutput()
        resc = bytes(res).decode('utf-8')
        print(resc)

    def pgktErrorHandler(self):
        err = self.prcs.readAllStandardError()
        errc = bytes(err).decode('utf-8')
        print(errc)

if __name__ == "__main__":
    app = QApplication([])
    window = Window()
    app.exec()
    sys.exit()

环境信息

  • Python 3.11
  • Windows 11
  • 使用Python 2.7运行pagekite.py
  • PyQt6

解决方案

问题根源是pagekite.py会自动检测输出环境:输出到交互式Shell时显示友好的人类可读信息;输出到非交互式管道(如QProcess的stdout)时,默认输出结构化日志格式。

1. 修改启动命令强制输出友好格式

在iniciaPageKite方法中添加--logformat=human参数,同时修正错误输出的信号连接:

def iniciaPageKite(self):
    self.prcs = QProcess()
    # 添加--logformat=human参数强制输出友好格式
    self.prcs.start('py', ['-2.7', 'pagekite.py', '--logformat=human', '80', 'test.pagekite.me'])
    self.prcs.readyReadStandardOutput.connect(self.pgktOutputHandler)
    # 修正:错误输出应连接到readyReadStandardError信号
    self.prcs.readyReadStandardError.connect(self.pgktErrorHandler)

2. 解析输出更新进度条

修改pgktOutputHandler函数,根据友好输出的关键字更新进度条状态:

def pgktOutputHandler(self):
    res = self.prcs.readAllStandardOutput()
    resc = bytes(res).decode('utf-8')
    print(resc)
    
    if "Connecting to front-end relay" in resc:
        self.defPrgBarPrg(25)
        self.defPrgBarClr("yellow")
    elif "Flying localhost" in resc:
        self.defPrgBarPrg(100)
        self.defPrgBarClr("green")
    elif "err=Rejected" in resc:
        self.defPrgBarPrg(0)
        self.defPrgBarClr("red")

注意事项

  • 可通过py -2.7 pagekite.py --help确认脚本是否支持--logformat参数
  • 若需同时获取结构化日志,可添加--logfile=./pagekite.log参数将日志写入文件,再从文件读取解析

内容的提问来源于stack exchange,提问作者Gustavo Salvador

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 01:15:53