A
A
Arthur Samurai2021-09-28 12:51:24
Python
Arthur Samurai, 2021-09-28 12:51:24

How to use multiprocessing in tkinter?

Good afternoon, mighty Habr.

I am using threads in this code :

Working window code
import os
import threading
import time

from tkinter import *
import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext


class MainWindow(tk.Frame):
    def __init__(self, root):
        super().__init__(root)
        self.init_main()


    def init_main(self):
        lb_log = Label(text=u"логин ")
        lb_log .pack()
        ent_value_log = Entry(width=40)
        ent_value_log .pack()
        lb_pass = Label(text=u"пароль ")
        lb_pass.pack()
        ent_value_pass = Entry(width=40)
        ent_value_pass.pack()
        btn_print = ttk.Button(text='print', command=lambda: self.printing(ent_value_log.get(), ent_value_pass.get()))
        btn_print .place(x=340, y=20)
        self.console = scrolledtext.ScrolledText(state='disable')
        self.console.pack(pady=15)


    def insert_to_console(self, text):
        self.console.configure(state='normal')  # enable insert
        self.console.insert(END, text)
        self.console.yview(END)  # autoscroll
        self.console.configure(state='disabled')


    def pr(self, login, password):
        self.insert_to_console(login + ' ' + password)
        time.sleep(5)
        self.insert_to_console(login + ' ' + password)
        time.sleep(5)

    def printing(self, login, password):
        pycrypt = threading.Thread(target=self.pr, args=(login, password))
        pycrypt.start()

    def run_app():
        root = tk.Tk()
        app = MainWindow(root)
        root.title("palevo")
        root.geometry("420x400")
        root.mainloop()

if __name__ == "__main__":
        zv = MainWindow
        zv.run_app()


And everything works. But I understand that for my program here - threading slows down work and I need to use processes. I've been smoking doc for 2 days and haven't smoked it yet. Without tkinter I can change
def printing(self, login, password):
        pycrypt = threading.Thread(target=self.pr, args=(login, password))
        pycrypt.start()

on the
def printing(self, login, password):
        pycrypt = Process(target=self.pr, args=(login, password))
        pycrypt.start()

and everything starts up. And the code runs faster.

But with tkinter, as soon as I do this I get an exception:
TypeError: cannot pickle '_tkinter.tkapp' object
EOFError: Ran out of input
on this line
pycrypt.start()

Help me figure out what I'm missing and how it can be started. As I understand it, I need to use queues or somehow indicate that tk.Tk () is the main process and associate it with the printing function.
So guess what this does is multiprocessing.Pipe and multiprocessing.Queue. But so far, attempts have been futile.

I would appreciate any help.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vindicar, 2021-09-28
@Vindicar

Proceed from the fact that between processes it is better to transfer only primitive data types and simple collections (lists, tuples, dictionaries). So don't pass Tkinter objects as they are, extract the required data from them and pass them.
EDIT:
The ideal scenario is to use the multiprocessing.Queue pair .
The child process code listens to one queue, and processes the tasks received there, and then writes responses to another.
The parent process code handles the GUI, stacks the jobs first, and occasionally monitors the second queue for new responses. Use root.after() for monitoring.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question