python - 如何添加 QProcess PATH 环境变量的路径?(Python 3.7 上的 PyQt5)
问题描述
1.问题说明
我QProcess()
在应用程序显示其主窗口之前实例化了一个 -object。QProcess()
-instance 存储在self.__myProcess
变量中,只要您能看到主窗口,它就会一直存在。
主窗口如下所示:
单击按钮时,将执行以下代码:
def __btn_clicked(self):
self.__add_openocd_to_env()
command = "openocd.exe" + '\r\n'
self.__myProcess.start(command)
最后两行非常清楚:命令openocd.exe
被传递给self.__myProcess
并执行。这个可执行文件实际上做了什么在这里并不重要。事实上,我可以使用任何随机的可执行文件。关键是:如果可执行文件在我的 WindowsPATH
环境变量中,它就会被找到并执行。
想象一下可执行文件不在PATH
环境变量中。然后该函数self.__add_openocd_to_env()
应该解决该问题:
def __add_openocd_to_env(self):
env = self.__myProcess.processEnvironment()
env.insert("PATH", "C:\\Users\\Kristof\\programs\\openocd_0.10.0\\bin;" + env.value("PATH"))
self.__myProcess.setProcessEnvironment(env)
但是,我注意到它根本没有效果。我在这个函数中尝试了很多不同的东西,但它不会有任何效果。
你可以在这里找到完整的代码:
如果你安装了 Python 3 和 PyQt5,你可以简单地将代码复制粘贴到一个 .py 模块中并运行它。您应该看到带有按钮的小窗口。当然,您应该将路径“C:\Users\Kristof..”更改为计算机上有效的路径。您可以为此测试选择任何您喜欢的可执行文件。
import sys
import os
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class CustomMainWindow(QMainWindow):
def __init__(self):
super(CustomMainWindow, self).__init__()
# -------------------------------- #
# QProcess() setup #
# -------------------------------- #
self.__myProcess = QProcess()
self.__myProcess.setProcessChannelMode(QProcess.MergedChannels)
self.__myProcess.readyRead.connect(self.__on_output)
self.__myProcess.errorOccurred.connect(self.__on_error)
self.__myProcess.finished.connect(self.__on_exit)
# -------------------------------- #
# Window setup #
# -------------------------------- #
self.setGeometry(100, 100, 800, 200)
self.setWindowTitle("QProcess test")
self.__frm = QFrame(self)
self.__frm.setStyleSheet("QWidget { background-color: #ffffff }")
self.__lyt = QVBoxLayout()
self.__lyt.setAlignment(Qt.AlignTop)
self.__frm.setLayout(self.__lyt)
self.setCentralWidget(self.__frm)
self.__myBtn = QPushButton("START QPROCESS()")
self.__myBtn.clicked.connect(self.__btn_clicked)
self.__myBtn.setFixedHeight(70)
self.__myBtn.setFixedWidth(200)
self.__lyt.addWidget(self.__myBtn)
self.show()
def __add_openocd_to_env(self):
env = self.__myProcess.processEnvironment()
env.insert("PATH", "C:\\Users\\Kristof\\programs\\openocd_0.10.0\\bin;" + env.value("PATH"))
self.__myProcess.setProcessEnvironment(env)
def __btn_clicked(self):
self.__add_openocd_to_env()
command = "openocd.exe" + '\r\n'
self.__myProcess.start(command)
def __on_output(self):
data = bytes(self.__myProcess.readAll()).decode().replace('\r\n', '\n')
print(data)
def __on_error(self, error):
print("")
print("Process error: {0}".format(str(error)))
print("")
def __on_exit(self, exitCode, exitStatus):
print("")
print("ExitCode = {0}".format(str(exitCode)))
print("ExitStatus = {0}".format(str(exitStatus)))
print("")
if __name__ == '__main__':
app = QApplication(sys.argv)
QApplication.setStyle(QStyleFactory.create('Fusion'))
myGUI = CustomMainWindow()
sys.exit(app.exec_())
2. 我的问题
我知道我可以PATH
在实例化QProcess()
. 但这不是重点。我想知道如何将它添加到PATH
那个特定实例的环境变量中QProcess()
。如果可能的话,它不应该影响QProcess()
我软件中的任何其他实例,也不应该影响QProcess()
我以后创建的任何未来实例。
3.系统设置
我在 Windows 10 上的 Python 3.7 中使用 PyQt5 框架。
注意:
我刚刚尝试通过QProcess()
以下方式改进设置:
# -------------------------------- #
# QProcess() setup #
# -------------------------------- #
self.__myProcess = QProcess()
self.__myProcess.setProcessChannelMode(QProcess.MergedChannels)
self.__myProcess.readyRead.connect(self.__on_output)
self.__myProcess.errorOccurred.connect(self.__on_error)
self.__myProcess.finished.connect(self.__on_exit)
# NEW: initialize the environment variables for self.__myProcess:
env = QProcessEnvironment.systemEnvironment()
self.__myProcess.setProcessEnvironment(env)
我很有希望......但它仍然无法正常工作:-(
解决方案
根据@JonBrave 先生的评论,我编写了以下解决方法:
import sys
import os
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class CustomMainWindow(QMainWindow):
def __init__(self):
super(CustomMainWindow, self).__init__()
# -------------------------------- #
# QProcess() setup #
# -------------------------------- #
self.__myProcess = QProcess()
self.__myProcess.setProcessChannelMode(QProcess.MergedChannels)
self.__myProcess.readyRead.connect(self.__on_output)
self.__myProcess.errorOccurred.connect(self.__on_error)
self.__myProcess.finished.connect(self.__on_exit)
# -------------------------------- #
# Window setup #
# -------------------------------- #
self.setGeometry(100, 100, 800, 200)
self.setWindowTitle("QProcess test")
self.__frm = QFrame(self)
self.__frm.setStyleSheet("QWidget { background-color: #ffffff }")
self.__lyt = QVBoxLayout()
self.__lyt.setAlignment(Qt.AlignTop)
self.__frm.setLayout(self.__lyt)
self.setCentralWidget(self.__frm)
self.__myBtn = QPushButton("START QPROCESS()")
self.__myBtn.clicked.connect(self.__btn_clicked)
self.__myBtn.setFixedHeight(70)
self.__myBtn.setFixedWidth(200)
self.__lyt.addWidget(self.__myBtn)
self.show()
def __add_openocd_to_env(self):
self.__oldEnv = os.environ["PATH"]
os.environ["PATH"] = "C:\\Users\\Kristof\\Dropbox (Personal)\\EMBEDOFFICE\\embedoffice\\resources\\programs\\openocd_0.10.0_dev00459\\bin;" + self.__oldEnv
def __remove_openocd_from_env(self):
os.environ["PATH"] = self.__oldEnv
def __btn_clicked(self):
self.__add_openocd_to_env()
command = "openocd.exe" + '\r\n'
self.__myProcess.start(command)
self.__myProcess.waitForStarted(-1)
self.__remove_openocd_from_env()
def __on_output(self):
data = bytes(self.__myProcess.readAll()).decode().replace('\r\n', '\n')
print(data)
def __on_error(self, error):
print("")
print("Process error: {0}".format(str(error)))
print("")
def __on_exit(self, exitCode, exitStatus):
print("")
print("ExitCode = {0}".format(str(exitCode)))
print("ExitStatus = {0}".format(str(exitStatus)))
print("")
if __name__ == '__main__':
app = QApplication(sys.argv)
QApplication.setStyle(QStyleFactory.create('Fusion'))
myGUI = CustomMainWindow()
sys.exit(app.exec_())
基本上我正在执行以下操作:就在命令QProcess()
-instance 启动命令之前,我将可执行路径添加到PATH
属于整个 Python 会话的环境变量。命令启动后,我可以再次删除它,这样它就不会影响QProcess()
将来创建的其他实例。
它有效,但如果我要在我的软件中应用这种方法(许多QProcess()
实例存在于我的软件中),它肯定需要大量的“簿记”。如果您找到更好的方法,请不要犹豫分享!
推荐阅读
- python - 我需要帮助来修复我的代码,以免从房间里拿东西两次
- html - 在 html 中分层图像和 div 大小
- python - 如何按月+年的顺序对数据框进行排序?
- java - 带有 maven 的 gitlab CI/CD 不会在 application.properties 中设置环境变量
- applescript - 仅从 AppleScript 中的字符串中提取字母字符
- android - 暂时隐藏Android中其他应用的通知
- azure - Azure - 在未启用事件中心捕获选项的情况下访问保留的事件中心数据
- rust - 循环中的多个可变引用
- google-sheets - 将工作表中的某些信息拉到主工作表中
- android - Kotlin 卡在 1.3.31 版本的 Android Studio 项目上