提问人:ABD 提问时间:8/20/2023 更新时间:8/20/2023 访问量:32
通过更改 sys.stdout 变量在 2 个 python 进程之间进行通信
Communicating between 2 python processes by changing sys.stdout variable
问:
我已经推了这个,但对我提出的解决方案感觉不好。 这是问题: 我创建了一个运行良好的命令行实用程序。
例如:我的 main.py 文件是
def Parser():
description = textwrap.dedent(
'''Main Command Line Tool.
For GUI based tool use: `main-gui`''')
parser = argparse.ArgumentParser(description=description, prog="main")
parser.add_argument("-f", "--foo", type=str, required=True, help='foo help')
parser.add_argument("-b", "--bar", type=str, help='bar help')
...
# this will not be shown in help
parser.add_argument("--GUI", action="store_true", help=argparse.SUPPRESS)
return parser
def task(args):
...
print("I am doing the task, Alright!") # this means print will call sys.stdout.write function
if args.GUI:
if hasattr(sys.stdout, "set_progress"): # double check. But this is always True if args.GUI is True
sys.stdout.set_progress(value)
...
def main():
parser = Parser()
args = parser.parse_args()
result = task(args)
if __name__ == "__main__":
main()
我运行它 哪个在终端/控制台/shell 中打印某些文本。基本上是 sys.stdoutmain --foo Hello --bar World
现在,我被要求为相同的 GUI 制作 GUI,所以我使用了 PySide6。
这是我 gui.py 文件:
import threading
from easydict import EasyDict
from PySide6.QtCore import ...
from PySide6.QtGui import ...
from PySide6.QtWidgets import ...
from main import main
class EmittingStream(QObject):
textWritten = Signal(str)
progress = Signal(int)
def write(self, text):
self.textWritten.emit(text)
def set_progress(self, value):
self.progress.emit(value)
def flush(self):
pass
class GUI(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
self.initArgs()
self.link_actions()
def initUI(self):
...
self.ui.progress_bar.setValue(0)
def initArgs(self):
self.args = EasyDict()
self.args.foo = None
self.args.bar = None
def link_actions(self):
...
self.ui.start_button.clicked.connect(self.start)
def setProgress(self, progress):
self.ui.progress_bar.setValue(progress)
def showOuput(self, s):
self.ui.output_textedit.append(s)
def clear_output_textedit(self):
self.ui.output_textedit.clear()
def get_args(self):
# Use the Gui text fields to access the foo and bar argument
# so self.arg.foo = Hello and so on for all arguments
# the arguments are exactly the same as the ones used for argparse
def start(self):
self.get_args()
command = ["main"]
command.extend(["--foo", self.args.foo])
command.extend(["--bar", self.args.bar])
## This specifically added in parser if the script is being called from GUI
## This doesn't show up when done main --help
command.extend(["--GUI"])
sys.argv = command
stream = EmittingStream()
sys.stdout = stream # This is what I beleive is Not good, But this work
stream.textWritten.connect(self.showOuput)
stream.progress.connect(self.setProgress)
analysis_thread = threading.Thread(target=main())
analysis_thread.start()
# Setting sys.stdout back to default
def __del__(self):
sys.stdout = sys.__stdout__
def gui():
app = QApplication(sys.argv)
window = GUI()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
gui()
我能够利用打印函数的引擎盖,它调用sys.stdout.write函数,该函数在EmittingStream中覆盖了它。 因此,每当在 main.py 中调用 print 时,它都会向 GUI 发送一个信号,然后我更新字段中的文本。
这很好用,所以我不再碰它了。 但是,困扰我的是更改 sys 变量来执行此操作。
这不是将 sys.stdout 作为参数传递给进程的重复,但确实给了我关于更改 sys.stdout 的想法
答: 暂无答案
评论
logging
sys.stdout
python some_file.py