首页 > 解决方案 > threading code.InteractiveInterpreter 并在执行命令时获取输出

问题描述

我正在尝试在 GUI pyqt5 中创建一个控制台,但我无法从 InteractiveInterpreter 获取输出。我不知道我的 InteractiveInterpreter 的线程是否正确。当我运行下面的代码(不尝试捕获输出)时,代码会按顺序打印,但我希望输出是这样的:

hi
0 interpreter
0 main
1 interpreter
1 main
2 interpreter
2 main
3 interpreter
4 interpreter

相反,我得到了这个:

hi
0 interpreter
1 interpreter
2 interpreter
3 interpreter
4 interpreter
0 main
1 main
2 main

代码:

import code
import threading
from time import sleep 
import sys
    

class IC(threading.Thread):
    def __init__(self, context=None):
      threading.Thread.__init__(self)
      
      self.Console = code.InteractiveInterpreter(context)

    def push(self, x, sym=''):
        return self.Console.runsource(x,sym)



if __name__ == "__main__":
    a=IC()
    a.start()
    a.push("print('hi')")
    a.push("from time import sleep")
    a.push("for i in range(5):\n\t print(i,'interpreter')\n\t sleep(1)\n")

    for i in range(3):
        print(i, 'main')
        sleep(1)

更新:我的代码现在像我预期的那样运行,但是我无法捕获打印语句。我尝试使用 contxtlib,但我得到的是正在打印的文本,但是在一个大块中。如何在打印语句出现时捕获它们,稍后我会将这些字符串传递给 qtextedit。

这是我现在使用的代码:

import code
import threading, queue
from time import sleep 
import sys

import io
from contextlib import redirect_stdout


class IC:
    def __init__(self):
        self.On = True
        self.qin = queue.Queue()
        self.qout = queue.Queue()
        self.thread = threading.Thread(target=self.runtime, daemon=True).start()

    def push(self, x):
        self.qin.put(x)

    def runtime(self):
        self.Console = code.InteractiveInterpreter()
        while self.On:
            f = io.StringIO()
            with redirect_stdout(f):
                if self.qin.qsize()>0:
                    self.Console.runsource(self.qin.get())
            if f.getvalue():
                print("caught:", f.getvalue())


if __name__ == "__main__":
    a=IC()
    a.push("print('hi')")
    a.push("from time import sleep")
    a.push("for i in range(5):\n\t print(i,'interpreter')\n\t sleep(2)\n")

    for i in range(3):
        print(i, 'main')
        sleep(1.5)

这是我得到的输出,处于空闲状态。前两行是我想要/期望的,但是当我进入 for 循环时,我必须等待它出来让我得到结果,而不是单独获取每个打印语句。

caught: 0 main

caught: hi

>>> caught: 0 interpreter
1 main
1 interpreter
2 main
2 interpreter
3 interpreter
4 interpreter

标签: pythonpython-3.xpyqt5

解决方案


@user2357112supportsMonica是正确的。您创建一个线程,然后启动该线程,但该线程没有做任何事情。交互式解释器在线程类中初始化,您向线程类添加了一个函数,但您所做的所有调用都来自主线程并在主线程上运行。

代码在您创建的线程内运行的唯一时间是代码在目标函数中。

我建议您查看 python 文档中的线程,并特别查看如何设置线程的目标以及如何在线程中循环以使其保持活动和工作。然后,您可能还需要考虑Queues将数据传递给新线程。


推荐阅读