PySimpleGUI 不会将 multiprocessing 的 cprint 重新路由到其 Multiline 元素

发布于 2025-01-14 00:25:57 字数 1674 浏览 5 评论 0原文

我正在使用 multiprocessing 模块和 PySimpleGUI

所有内容都打印在我的 IDE 控制台中,而不是 Multiline。仅当我使用多处理时才会出现此问题。其他带有 sg.cprint 语句的函数,甚至带有简单的 print 语句的函数也会以 Multiline 的形式打印结果,就像它应该的那样。

这是我的代码,它显示了我尝试使用 reroute_stdout=True 将所有内容重新路由到 Multiline 的问题

import PySimpleGUI as sg
import multiprocessing


def func(link: str):
    sg.cprint(link)
    sg.cprint('string')
    print(link)
    print('string')


def make_window():
    layout = [[sg.Multiline(key='-Multiline-', reroute_stdout=True)],
              [[sg.Button('Start', key='-Start-')]]]

    window = sg.Window('Forum', layout, finalize=True)

    sg.cprint_set_output_destination(window, '-Multiline-')

    while True:
        event, values = window.read()
        if event == sg.WIN_CLOSED:
            break

        elif event == '-Start-':
            sg.cprint('Process has started')
            process = multiprocessing.Process(target=func,
                                              args=('https://stackoverflow.com/questions/ask',),
                                              daemon=True)
            process.start()

    window.close()


if __name__ == '__main__':
    make_window()

- 不起作用。 根据 PySimpleGUI 的所谓“Cookbook”,可以像这样重新路由打印:

window['-Multiline-'].print('Testing 1 2 3')

如果我在函数中放入类似的内容,它就不起作用(我认为这是因为我的函数位于GUI 代码)

总之 - 当我使用 threading 模块时,问题不会出现。但是multiprocessing解决了其他问题 - 它允许我使用.terminate()终止进程。使用线程无法轻松做到这一点。

我的应用程序使用 OOP,比我提供的代码稍微复杂一些。

I am using multiprocessing module along with PySimpleGUI.

Instead of Multiline everything gets printed in my IDE console. This problem only happens when I use multiprocessing. Other function with sg.cprint statement and even with simple print statement would print the result in Multiline, as it should.

Here's my code, that shows the problem

import PySimpleGUI as sg
import multiprocessing


def func(link: str):
    sg.cprint(link)
    sg.cprint('string')
    print(link)
    print('string')


def make_window():
    layout = [[sg.Multiline(key='-Multiline-', reroute_stdout=True)],
              [[sg.Button('Start', key='-Start-')]]]

    window = sg.Window('Forum', layout, finalize=True)

    sg.cprint_set_output_destination(window, '-Multiline-')

    while True:
        event, values = window.read()
        if event == sg.WIN_CLOSED:
            break

        elif event == '-Start-':
            sg.cprint('Process has started')
            process = multiprocessing.Process(target=func,
                                              args=('https://stackoverflow.com/questions/ask',),
                                              daemon=True)
            process.start()

    window.close()


if __name__ == '__main__':
    make_window()

I have tried to reroute everything to Multiline with reroute_stdout=True — doesn't work.
According to so called "Cookbook" of PySimpleGUI, it's possible to reroute print like this:

window['-Multiline-'].print('Testing 1 2 3')

It doesn't work if I put something like that in my function (I assume that is because my function is above the GUI code)

In conclusion - the issue doesn't appear when I use threading module. But multiprocessing solves other problem - it allows me to terminate a process with .terminate(). Couldn't do that with threadingas easily.

My application uses OOP and a bit more complicated than the code I provided.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暮光沉寂 2025-01-21 00:25:57

运行子进程时,您将获得一个全新的环境。例如,您不能共享全局变量。

每当你 start() 一个 multiprocess.Process 实例时,Python 本质上都会运行一个全新的 Python 解释器实例,并且由于不同的进程获得不同的堆栈,因此它们无法共享内部内存,因此 Python 实际上会腌制传递的参数,将它们发送到进程,然后在那里取消它们,从而产生两个进程(父进程和子进程)具有相同数据的错觉。

我对库multiprocessing一无所知,遵循代码工作,但可能并不完美。

from time import sleep
import threading
import multiprocessing

import PySimpleGUI as sg

def func(queue:multiprocessing.Queue, link: str):
    for i in range(10):
        queue.put(f'Message #{i}')
        sleep(1)

def thread(window, url):
    queue = multiprocessing.Queue()
    process = multiprocessing.Process(target=func, args=(queue, url), daemon=True)
    process.start()
    while process.is_alive():
        if not queue.empty():
            line = queue.get()
            window.write_event_value("Message", line)
    while not queue.empty():
        line = queue.get()
        window.write_event_value("Message", line)
    window.write_event_value("Message", 'Process has stopped')

def make_window():
    layout = [[sg.Multiline(key='-Multiline-', size=(40, 10), reroute_stdout=True)],
              [[sg.Button('Start', key='-Start-')]]]

    window = sg.Window('Forum', layout, finalize=True)

    sg.cprint_set_output_destination(window, '-Multiline-')

    while True:
        event, values = window.read()
        if event == sg.WIN_CLOSED:
            break

        elif event == '-Start-':
            sg.cprint('Process has started')
            url = 'https://stackoverflow.com/questions/ask'
            threading.Thread(target=thread, args=(window, url), daemon=True).start()
        elif event == 'Message':
            message = values[event]
            print(message)

    window.close()

if __name__ == '__main__':
    make_window()

When running a subprocess, you get an entirely new environment. You can't share global variables for example.

Python essentially runs a completely new Python interpreter instance whenever you start() a multiprocess.Process instance and since different processes get different stacks they don't get to share the internal memory so Python actually pickles the passed arguments, sends them to the Process and then unpickles them there creating an illusion that both processes (the parent and the child) have the same data.

I know nothing about library multiprocessing, following code work, but maybe not perfect.

from time import sleep
import threading
import multiprocessing

import PySimpleGUI as sg

def func(queue:multiprocessing.Queue, link: str):
    for i in range(10):
        queue.put(f'Message #{i}')
        sleep(1)

def thread(window, url):
    queue = multiprocessing.Queue()
    process = multiprocessing.Process(target=func, args=(queue, url), daemon=True)
    process.start()
    while process.is_alive():
        if not queue.empty():
            line = queue.get()
            window.write_event_value("Message", line)
    while not queue.empty():
        line = queue.get()
        window.write_event_value("Message", line)
    window.write_event_value("Message", 'Process has stopped')

def make_window():
    layout = [[sg.Multiline(key='-Multiline-', size=(40, 10), reroute_stdout=True)],
              [[sg.Button('Start', key='-Start-')]]]

    window = sg.Window('Forum', layout, finalize=True)

    sg.cprint_set_output_destination(window, '-Multiline-')

    while True:
        event, values = window.read()
        if event == sg.WIN_CLOSED:
            break

        elif event == '-Start-':
            sg.cprint('Process has started')
            url = 'https://stackoverflow.com/questions/ask'
            threading.Thread(target=thread, args=(window, url), daemon=True).start()
        elif event == 'Message':
            message = values[event]
            print(message)

    window.close()

if __name__ == '__main__':
    make_window()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文