当前位置: 首页 > 知识库问答 >
问题:

在Python中重定向stdout到PyGame

张高澹
2023-03-14

我这里有一个非常奇怪的用例,我正试图为我的学生编写一些简单的程序,帮助他们学习python。为了让它工作,我在TKinter框架中嵌入了一个PyGame窗口,我需要重定向stdout以更改PyGame窗口中的某些内容。我有重定向工作,如果我重定向到一个文件,它的工作很好,但如果我试图改变文本,它不工作。我将一个字符串硬编码到PyGame文本更改代码中,这是可行的,但由于某些原因,它无法与重定向文本一起工作。

重定向类:

class PrintTest:
    def __init__(self, file, game):
        self.f = file
        self.game = game
    
    def write(self, t):
        f.write(t)

        self.game.text = game.font.render(t, True, self.game.text_colors[1], self.game.text_colors[2])
        self.game.textRect = self.game.text.get_rect()

        self.game.textRect.center = (300, 300)

    def flush(self):
        pass

游戏类:

class Game:
    def __init__(self, root):
        self.root = root
        embed = tk.Frame(root, width=600, height=600)
        embed.pack(side=tk.LEFT)

        os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
        if platform.system == "Windows":
            os.environ['SDL_VIDEODRIVER'] = 'windib'

        self.text_colors = [(255,255,255),
                            (0,255,0),
                            (0,0,128)]

        # initialize a pygame display
        pygame.init()
        self.screen = pygame.display.set_mode((600, 600))
        self.screen.fill(pygame.Color('red'))
        self.clock = pygame.time.Clock()

        self.font = pygame.font.Font('freesansbold.ttf', 32)
        self.text = self.font.render('Hello, world!', True, self.text_colors[1], self.text_colors[2])
        self.textRect = self.text.get_rect()

        self.textRect.center = (300, 300)

        # TK Creation
        helv = font.Font(family='Helvetica', size=18, weight='bold')
        self.button = tk.Button(root, 
                                text="Change text",
                                font=helv,
                                command=self.change_text).pack()

        self.user_input = tk.StringVar()
        self.textbox = ttk.Entry(root, width=15, textvariable=self.user_input)
        self.textbox.pack()
        # ---------------------------------------------------------------

    def change_text(self):
        print(self.user_input.get())

    def run(self):
        # Pygame loop
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

            self.screen.fill(pygame.Color('red'))    

            self.screen.blit(self.text, self.textRect)

            pygame.display.update()

            try:
                self.root.update()
            except tk.TclError:
                running = False   
        pygame.quit()

我把标准设置成这样:

try:
    root = tk.Tk()
    root.geometry('1000x600')

    game = Game(root)

    f = open('text.txt', 'w')
    sl = PrintTest(f, game)
    sys.stdout = sl

    game.run()
except Exception:
    traceback.print_exc()
    pygame.quit()

当我按原样运行时,如果我在框中键入hello,hello将打印到文件中,但pygame框中会放入一个空字符。我对PyGame真的不太了解,不知道这到底是一个问题还是一个重定向问题。任何帮助都将不胜感激!

(如果你想知道这里的用例是什么,我要让他们“完成”一些程序,让PyGame中发生一些事情。所以如果他们输入打印(“你好,朋友!”)到给定的字段,它将重定向到PyGame框中的某个人的对话框。从长远来看,这可能行不通,但我必须克服这一点才能真正弄清楚)

编辑:

所以问题是,由于某种原因,当我单击按钮时,write函数被调用了两次,它在键入的字符串上调用print,然后在空字符串上再次调用print。仍然不确定如何修复,但至少我发现了问题

共有1个答案

郑松
2023-03-14

好吧,我找到问题了。

看起来print向stdout发送了两样东西,要print的字符串和结尾字符。所以它覆盖了我想要用换行符打印的字符串。我改变了我的PrintTest类以适应这一点:

class PrintTest:
    def __init__(self, file, game):
        self.f = file
        self.game = game

    def write(self, t):
        if t != '\n':
            self.f.write(t)
            self.game.text, self.game.textRect = game.font.render(t, self.game.text_colors[2])

            self.game.textRect.center = (300, 300)

    def flush(self):
        pass
 类似资料:
  • 问题内容: 如何在Python中将stdout重定向到任意文件? 当从ssh会话中启动运行了很长时间的Python脚本(例如,Web应用程序)并进行背景调整,并且ssh会话关闭时,该应用程序将在尝试写入stdout时引发并失败。我需要找到一种方法来使应用程序和模块输出到文件而不是stdout,以防止由于而导致失败。当前,我使用将输出重定向到文件,并且可以完成工作,但是我想知道是否有一种出于好奇而无

  • 问题内容: 我在cyberciti.biz的评论中看到了这个有趣的问题。 我发现我什至找不到在sh的单行命令中执行此操作的灵活方法。 到目前为止,我对解决方案的想法是: 但是您会看到,这不是同步的,而且致命的是,它是如此丑陋。 欢迎与您分享这个想法。:) 问题答案: 你要 这里的顺序很重要。假设stdin(fd 0),stdout(fd 1)和stderr(fd 2)最初都连接到tty,因此 首先

  • 问题内容: 我试图重定向java中子进程的stdin和stdout,最终我将把输出转到JTextArea或其他东西。 这是我当前的代码, 输出如下所示: 我期望看到输出“ Hello World”字符串。也许是因为父进程的存活时间不够长? 我还希望能够发送和接收多个命令。 问题答案: 在尝试侦听输入流之前,您已经尝试写入输出流,因此您什么也没看到是有道理的。为使此成功,您将需要对两个流使用单独的线

  • 问题内容: 我想从Groovy程序中执行foo.bat,并将生成的进程的输出重定向到stdout。Java或Groovy代码示例都可以。 foo.bat可能需要花费几分钟才能运行并生成大量输出,因此我希望在生成后立即查看输出,而不是必须等到该过程完成之后才能立即查看所有输出。 问题答案: 它使用一个类读取执行的程序生成的所有输出,并将其显示在其自己的stdout中。

  • 问题内容: 我想将子进程的stderr输出重定向到stdout。常量应该这样做,不是吗? 然而, 确实 输出了一些东西。为什么会这样,如何在stdout上得到错误消息? 问题答案: 仔细阅读源代码即可得出答案。特别是,该文档在显示以下内容时会产生误导: 表示(…)的特殊值表示标准错误应与标准输出进入同一 句柄 。 由于在求值时stdout设置为“默认”(技术上来说),因此stderr也设置为“默认

  • 问题内容: 我知道如何将标准输出重定向到文件,但是我不知道如何将其重定向到字符串。 问题答案: 是的-您可以使用: 然后您可以使用获取字符串。 要指定编码(而不依赖平台定义的编码),请使用构造函数,然后 如果要还原为原始流,请使用: