Skip to content

Commit 2efce32

Browse files
committed
交互执行命令
1 parent 62040b5 commit 2efce32

File tree

4 files changed

+139
-1
lines changed

4 files changed

+139
-1
lines changed

QProcess/InteractiveRun.py

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
"""
4+
Created on 2023/02/01
5+
@author: Irony
6+
@site: https://pyqt.site https://github.com/PyQt5
7+
8+
@file: InteractiveRun.py
9+
@description:
10+
"""
11+
12+
import os
13+
import sys
14+
15+
try:
16+
import chardet
17+
except ImportError:
18+
print('chardet not found')
19+
20+
try:
21+
from PyQt5.QtCore import QProcess
22+
from PyQt5.QtWidgets import (QApplication, QLineEdit, QPushButton,
23+
QTextBrowser, QVBoxLayout, QWidget)
24+
except ImportError:
25+
from PySide2.QtCore import QProcess
26+
from PySide2.QtWidgets import (QApplication, QLineEdit, QPushButton,
27+
QTextBrowser, QVBoxLayout, QWidget)
28+
29+
30+
class Window(QWidget):
31+
32+
def __init__(self, *args, **kwargs):
33+
super(Window, self).__init__(*args, **kwargs)
34+
layout = QVBoxLayout(self)
35+
36+
command = 'ping www.baidu.com'
37+
if sys.platform.startswith('win'):
38+
command = 'ping -n 5 www.baidu.com'
39+
elif sys.platform.startswith('darwin') or sys.platform.startswith(
40+
'linux'):
41+
command = 'ping -c 5 www.baidu.com'
42+
else:
43+
raise RuntimeError('Unsupported platform: %s' % sys.platform)
44+
45+
self.cmdEdit = QLineEdit(command, self)
46+
layout.addWidget(self.cmdEdit)
47+
48+
self.buttonRun = QPushButton('执行命令', self)
49+
layout.addWidget(self.buttonRun)
50+
self.buttonRun.clicked.connect(self.run_command)
51+
52+
self.resultView = QTextBrowser(self)
53+
layout.addWidget(self.resultView)
54+
55+
self._cmdProcess = None
56+
self._init()
57+
58+
def closeEvent(self, event):
59+
if self._cmdProcess:
60+
self._cmdProcess.writeData('exit'.encode() + os.linesep.encode())
61+
self._cmdProcess.waitForFinished()
62+
if self._cmdProcess:
63+
self._cmdProcess.terminate()
64+
super(Window, self).closeEvent(event)
65+
66+
def _init(self):
67+
if self._cmdProcess:
68+
return
69+
# 打开终端shell
70+
self._cmdProcess = QProcess(self)
71+
self._cmdProcess.setProgram(
72+
'cmd' if sys.platform.startswith('win') else 'bash')
73+
# 合并输出流和错误流,只从标准输出流读取数据
74+
self._cmdProcess.setProcessChannelMode(QProcess.MergedChannels)
75+
self._cmdProcess.started.connect(self.on_started)
76+
self._cmdProcess.finished.connect(self.on_finished)
77+
self._cmdProcess.errorOccurred.connect(self.on_error)
78+
self._cmdProcess.readyReadStandardOutput.connect(
79+
self.on_readyReadStandardOutput)
80+
self._cmdProcess.start()
81+
82+
def run_command(self):
83+
self._init()
84+
command = self.cmdEdit.text().strip()
85+
if not command:
86+
return
87+
command = command.encode(sys.getdefaultencoding()) + os.linesep.encode(
88+
sys.getdefaultencoding())
89+
self._cmdProcess.writeData(command)
90+
91+
def on_started(self):
92+
self.resultView.append('ping process started, pid: %s' %
93+
self._cmdProcess.processId())
94+
95+
def on_finished(self, exitCode, exitStatus):
96+
print('ping process finished, exitCode: %s, exitStatus: %s' %
97+
(exitCode, exitStatus))
98+
self._cmdProcess.kill()
99+
self._cmdProcess = None
100+
101+
def on_error(self, error):
102+
self.resultView.append('ping process error: %s, message: %s' %
103+
(error, self._cmdProcess.errorString()))
104+
self._cmdProcess.kill()
105+
self._cmdProcess = None
106+
107+
def on_readyReadStandardOutput(self):
108+
# 读取已有结果
109+
result = self._cmdProcess.readAllStandardOutput().data()
110+
try:
111+
encoding = chardet.detect(result)
112+
self.resultView.append(result.decode(encoding['encoding']))
113+
except Exception:
114+
self.resultView.append(result.decode('utf-8', errors='ignore'))
115+
116+
117+
if __name__ == '__main__':
118+
import cgitb
119+
120+
cgitb.enable(format='text')
121+
app = QApplication(sys.argv)
122+
w = Window()
123+
w.show()
124+
sys.exit(app.exec_())

QProcess/README.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- 目录
44
- [执行命令得到结果](#1执行命令得到结果)
5+
- [交互执行命令](#2交互执行命令)
56

67
## 1、执行命令得到结果
78
[运行 GetCmdResult.py](GetCmdResult.py)
@@ -17,4 +18,16 @@
1718
2. `waitForFinished`为同步方式,然后调用`readAll`读取所有输出
1819
3. 也可以绑定`finished`信号,然后通过`readAll`读取所有输出
1920

20-
![GetCmdResult](ScreenShot/GetCmdResult.gif)
21+
![GetCmdResult](ScreenShot/GetCmdResult.gif)
22+
23+
## 2、交互执行命令
24+
[运行 InteractiveRun.py](InteractiveRun.py)
25+
26+
`QProcess` 也可以用于交互式执行命令,具体需要如下几步:
27+
28+
1. 通过`setProcessChannelMode(QProcess.MergedChannels)`合并标准输出和错误输出
29+
2. 通过`start`启动进程
30+
3. 通过`readyReadStandardOutput`信号读取进程输出
31+
4. 通过`writeData`向进程写入数据
32+
33+
![InteractiveRun](ScreenShot/InteractiveRun.gif)
110 KB
Loading

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@
242242
- [串口调试小助手](QSerialPort/SerialDebugAssistant.py)
243243
- [QProcess](QProcess)
244244
- [执行命令得到结果](QProcess/GetCmdResult.py)
245+
- [交互执行命令](QProcess/InteractiveRun.py)
245246
- [QProxyStyle](QProxyStyle)
246247
- [Tab文字方向](QProxyStyle/TabTextDirection.py)
247248
- [Tab角落控件位置占满](QProxyStyle/TabCornerWidget.py)

0 commit comments

Comments
 (0)