Skip to content

Commit

Permalink
执行命令得到结果 PyQt5#174
Browse files Browse the repository at this point in the history
  • Loading branch information
892768447 committed Feb 1, 2023
1 parent 6dbe593 commit 62040b5
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 0 deletions.
116 changes: 116 additions & 0 deletions QProcess/GetCmdResult.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2023/02/01
@author: Irony
@site: https://pyqt.site https://github.com/PyQt5
@email: [email protected]
@file: GetCmdResult.py
@description:
"""

import sys

try:
from PyQt5.QtCore import QProcess
from PyQt5.QtWidgets import (QApplication, QLabel, QPushButton,
QTextBrowser, QVBoxLayout, QWidget)
except ImportError:
from PySide2.QtCore import QProcess
from PySide2.QtWidgets import (QApplication, QLabel, QPushButton,
QTextBrowser, QVBoxLayout, QWidget)


class Window(QWidget):

def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.setWindowTitle('执行命令得到结果')
layout = QVBoxLayout(self)
layout.addWidget(QLabel('点击执行 ping www.baidu.com', self))

self.buttonRunSync = QPushButton('同步执行', self)
layout.addWidget(self.buttonRunSync)
self.buttonRunSync.clicked.connect(self.run_ping)

self.buttonRunASync = QPushButton('异步执行', self)
layout.addWidget(self.buttonRunASync)
self.buttonRunASync.clicked.connect(self.run_ping)

self.resultView = QTextBrowser(self)
layout.addWidget(self.resultView)

self._pingProcess = None

def run_ping(self):
sender = self.sender() # 同步或者异步按钮
self.buttonRunSync.setEnabled(False)
self.buttonRunASync.setEnabled(False)

if self._pingProcess:
self._pingProcess.terminate()

self._pingProcess = QProcess(self)
self._pingProcess.setProgram('ping')
if sys.platform.startswith('win'):
self._pingProcess.setArguments(['-n', '5', 'www.baidu.com'])
self._pingProcess.setArguments(['-n', '5', 'www.baidu.com'])
elif sys.platform.startswith('darwin') or sys.platform.startswith(
'linux'):
self._pingProcess.setArguments(['-c', '5', 'www.baidu.com'])
# 合并输出流和错误流,执行完毕后通过readAll可以一次性读取所有结果
self._pingProcess.setProcessChannelMode(QProcess.MergedChannels)
self._pingProcess.started.connect(self.on_started)

if sender == self.buttonRunASync:
# 异步执行
self._pingProcess.finished.connect(self.on_finished)
self._pingProcess.errorOccurred.connect(self.on_error)
self._pingProcess.start()
elif sender == self.buttonRunSync:
# 同步执行
self._pingProcess.start()
if self._pingProcess.waitForFinished():
self.on_finished(self._pingProcess.exitCode(),
self._pingProcess.exitStatus())
else:
self.resultView.append('ping process read timeout')
self.on_error(self._pingProcess.error())

def on_started(self):
self.resultView.append('ping process started')

def on_finished(self, exitCode, exitStatus):
self.resultView.append(
'ping process finished, exitCode: %s, exitStatus: %s' %
(exitCode, exitStatus))
# 读取所有结果
result = self._pingProcess.readAll().data()
try:
import chardet
encoding = chardet.detect(result)
self.resultView.append(result.decode(encoding['encoding']))
except Exception:
self.resultView.append(result.decode('utf-8', errors='ignore'))
self._pingProcess.kill()
self._pingProcess = None
self.buttonRunSync.setEnabled(True)
self.buttonRunASync.setEnabled(True)

def on_error(self, error):
self.resultView.append('ping process error: %s, message: %s' %
(error, self._pingProcess.errorString()))
self._pingProcess.kill()
self._pingProcess = None
self.buttonRunSync.setEnabled(True)
self.buttonRunASync.setEnabled(True)


if __name__ == '__main__':
import cgitb

cgitb.enable(format='text')
app = QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())
Empty file added QProcess/README.en.md
Empty file.
20 changes: 20 additions & 0 deletions QProcess/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# QProcess

- 目录
- [执行命令得到结果](#1执行命令得到结果)

## 1、执行命令得到结果
[运行 GetCmdResult.py](GetCmdResult.py)

`QProcess` 常用执行命令方式有以下几种:
1. `QProcess.execute('ping', ['www.baidu.com'])`:同步执行,返回值为进程退出码
2. `QProcess.startDetached('ping', ['www.baidu.com'], '工作路径')`:返回值为是否启动成功,该命令一般用于启动某个程序后就不管了
3. 通过构造`QProcess`对象,然后通过`QProcess.start()`启动进程,并分为同步和异步两种方式获取输出

示例代码为第3种方式:

1. 通过`setProcessChannelMode(QProcess.MergedChannels)`合并标准输出和错误输出
2. `waitForFinished`为同步方式,然后调用`readAll`读取所有输出
3. 也可以绑定`finished`信号,然后通过`readAll`读取所有输出

![GetCmdResult](ScreenShot/GetCmdResult.gif)
Binary file added QProcess/ScreenShot/GetCmdResult.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@
- [分割窗口的分割条重绘](QSplitter/RewriteHandle.py)
- [QSerialPort](QSerialPort)
- [串口调试小助手](QSerialPort/SerialDebugAssistant.py)
- [QProcess](QProcess)
- [执行命令得到结果](QProcess/GetCmdResult.py)
- [QProxyStyle](QProxyStyle)
- [Tab文字方向](QProxyStyle/TabTextDirection.py)
- [Tab角落控件位置占满](QProxyStyle/TabCornerWidget.py)
Expand Down

0 comments on commit 62040b5

Please sign in to comment.