ForkingPickler (файл, протокол) .dump (obj) TypeError: невозможно обработать объект '_tkinter.tkapp' - PullRequest
0 голосов
/ 09 июля 2020

Ниже мой код: моя функция получает блоки данных с сервера и помещает их в буфер FIFO, после чего две функции вызываются параллельно,

recvData () # продолжать получать блоки данных с сервера и помещать их в буфер FIFO calculate_threshold () # для удаления блоков данных из буфера FIFO и выполнения некоторых вычислений, отображения в реальном времени на GUI и записи результата в файл

Код


import socket
import turtle
#import timeit
import queue
import multiprocessing
from tkinter import *

class GUI:

    def __init__(self, master):
        self.master = master
        master.title("Collision Detection")
    
        self.buff_data = queue.Queue()

        self.p1 = multiprocessing.Process(target = self.recvData)
        self.p1 = multiprocessing.Process(target=self.calculate_threshold)
    
        self.input_label = Label(root, text = "Input all the gratings set straight wavelength values in nm")
        self.input_label.grid(row = 0)
    
        self.core_string = "Core "
        self.entries = []

        self.label_col_inc = 0
        self.entry_col_inc = 1
        self.core_range = range(1, 5)

        for y in self.core_range:
            self.core_text = self.core_string + str(y) + '_' + '25'
            self.core_label = Label(root, text = self.core_text)
            self.entry = Entry(root)
            self.core_label.grid(row=1, column=self.label_col_inc, sticky=E)
            self.entry.grid(row=1, column=self.entry_col_inc)
            self.entries.append(self.entry)
            self.label_col_inc += 2
            self.entry_col_inc += 2
    
        self.threshold_label = Label(root, text = "Threshold in nm")
        self.entry_threshold = Entry(root)

        self.threshold_label.grid(row = 2, sticky = E)
        self.entry_threshold.grid(row = 2, column = 1)
    
        self.light_label = Label(root, text = 'Status')
        self.light_label.grid(row = 3, column = 3)

        self.canvas = Canvas(root, width = 150, height = 50)
        self.canvas.grid(row = 4, column = 3)
    
        # Green light
        self.green_light = turtle.RawTurtle(self.canvas)
        self.green_light.shape('circle')
        self.green_light.color('grey')
        self.green_light.penup()
        self.green_light.goto(0,0)

        # Red light
        self.red_light = turtle.RawTurtle(self.canvas)
        self.red_light.shape('circle')
        self.red_light.color('grey')
        self.red_light.penup()
        self.red_light.goto(40,0)
    
        self.data_button = Button(root, text = "Get data above threshold", command = self.getData)
        self.data_button.grid(row = 5, column = 0)


# function to receive TCP data blocks
    def getData(self):
        host = '127.0.0.1'
        port = 5000
        s = socket.socket()
        s.connect((host, port))

        len_message = s.recv(4)
        bytes_length = int(len_message.decode('utf-8'))  # for the self-made server
        recvd_data = s.recv(bytes_length)
        self.buff_data.put(recvd_data)
        self.p1.start()
        self.p2.start()

        self.p1.join()
        self.p2.join()

        
    def recvData(self):
        len_message = s.recv(4)
        while len_message:
            bytes_length = int(len_message.decode('utf-8'))  # for the self-made server
            recvd_data = s.recv(bytes_length)
            self.buff_data.put(recvd_data)
            len_message = s.recv(4)

        else:
            print('out of loop')
        s.close()


    def calculate_threshold(self):
        rmv_data = self.buff_data.get()
        stringdata = rmv_data.decode('utf-8')
        rep_str = stringdata.replace(",", ".")
        splitstr = rep_str.split()

        # received wavelength values
        inc = 34
        wav_threshold = []
        for y in self.entries:
            straight_wav = float(y.get())
            wav = float(splitstr[inc])
            wav_diff = wav - straight_wav
            if wav_diff < 0:
                wav_diff = wav_diff * (-1)
            wav_threshold.append(wav_diff)
            inc += 56

        threshold = float(self.entry_threshold.get())

        # writing into the file
        data = []
        inc1 = 0
        col1 = 2
        col2 = 6

        data.insert(0, (str(splitstr[0])))
        data.insert(1, (str(splitstr[1])))

        for x in wav_threshold:
            if (x > threshold):
                self.red_light.color('red')
                self.green_light.color('grey')
                data.insert(col1, (str(splitstr[34 + inc1])))
                data.insert(col2,(str(x)))
            else:
                self.red_light.color('grey')
                self.green_light.color('green')
                data.insert(col1,'-')
                data.insert(col2,'-')
            inc1 += 56
            col1 += 1
            col2 += 1

        self.write_file(data)



# function to write into the file
    def write_file(self,data):
        with open("Output.txt", "a") as text_file:
            text_file.write('\t'.join(data[0:]))
            text_file.write('\n')

if __name__ == '__main__':
    root = Tk()
    gui = GUI(root)
    root.mainloop()

Но я получаю следующую ошибку:


Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "C:/Users/PycharmProjects/GUI/GUI_v4.py", line 88, in getData
    self.p1.start()
  File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\process.py", line 121, in start
    self._popen = self._Popen(self)
  File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\context.py", line 326, in _Popen
    return Popen(process_obj)
  File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle '_tkinter.tkapp' object
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\spawn.py", line 116, in spawn_main
    exitcode = _main(fd, parent_sentinel)
  File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\multiprocessing\spawn.py", line 126, in _main
    self = reduction.pickle.load(from_parent)
EOFError: Ran out of input

Может ли кто-нибудь сказать, где именно я здесь ошибаюсь?

Ответы [ 2 ]

0 голосов
/ 09 июля 2020

Код изменился после создания нового класса:

import socket
import turtle
# import timeit
import queue
import multiprocessing
from tkinter import *


class GUI:

    def __init__(self, master):
        self.master = master
        master.title("Collision Detection")

        self.input_label = Label(root, text="Input all the gratings set straight wavelength values in nm")
        self.input_label.grid(row=0)

        self.core_string = "Core "
        self.entries = []


        self.label_col_inc = 0
        self.entry_col_inc = 1
        self.core_range = range(1, 5)

        for y in self.core_range:
            self.core_text = self.core_string + str(y) + '_' + '25'
            self.core_label = Label(root, text=self.core_text)
            self.entry = Entry(root)
            self.core_label.grid(row=1, column=self.label_col_inc, sticky=E)
            self.entry.grid(row=1, column=self.entry_col_inc)
            self.entries.append(self.entry)
            self.label_col_inc += 2
            self.entry_col_inc += 2

        self.threshold_label = Label(root, text="Threshold in nm")
        self.entry_threshold = Entry(root)

        self.threshold_label.grid(row=2, sticky=E)
        self.entry_threshold.grid(row=2, column=1)

        self.light_label = Label(root, text='Status')
        self.light_label.grid(row=3, column=3)

        self.canvas = Canvas(root, width=150, height=50)
        self.canvas.grid(row=4, column=3)

        # Green light
        self.green_light = turtle.RawTurtle(self.canvas)
        self.green_light.shape('circle')
        self.green_light.color('grey')
        self.green_light.penup()
        self.green_light.goto(0, 0)

        # Red light
        self.red_light = turtle.RawTurtle(self.canvas)
        self.red_light.shape('circle')
        self.red_light.color('grey')
        self.red_light.penup()
        self.red_light.goto(40, 0)

        self.data_button = Button(root, text="Get data above threshold", command=recv_data.getData)
        self.data_button.grid(row=5, column=0)


class recv_data:
    def __init__(self):
        self.buff_data = queue.Queue()
        self.p1 = multiprocessing.Process(target=self.recvData)
        self.p1 = multiprocessing.Process(target=self.calculate_threshold)
        self.host = '127.0.0.1'
        self.port = 5002
        self.s = socket.socket()
        self.s.connect((self.host, self.port))

    # function to receive TCP data blocks
    def getData(self):
        len_message = self.s.recv(4)
        bytes_length = int(len_message.decode('utf-8'))  # for the self-made server
        recvd_data = self.s.recv(bytes_length)
        self.buff_data.put(recvd_data)
        self.p1.start()
        self.p2.start()

        self.p1.join()
        self.p2.join()

    def recvData(self):
        len_message = self.s.recv(4)
        while len_message:
            bytes_length = int(len_message.decode('utf-8'))  # for the self-made server
            recvd_data = self.s.recv(bytes_length)
            self.buff_data.put(recvd_data)
            len_message = self.s.recv(4)

        else:
            print('out of loop')
        self.s.close()

    def calculate_threshold(self):
        rmv_data = self.buff_data.get()
        stringdata = rmv_data.decode('utf-8')
        rep_str = stringdata.replace(",", ".")
        splitstr = rep_str.split()

        # received wavelength values
        inc = 34
        wav_threshold = []
        for y in gui.entries:
            straight_wav = float(y.get())
            wav = float(splitstr[inc])
            wav_diff = wav - straight_wav
            if wav_diff < 0:
                wav_diff = wav_diff * (-1)
            wav_threshold.append(wav_diff)
            inc += 56

        threshold = float(gui.entry_threshold.get())

        # writing into the file
        data = []
        inc1 = 0
        col1 = 2
        col2 = 6

        data.insert(0, (str(splitstr[0])))
        data.insert(1, (str(splitstr[1])))

        for x in wav_threshold:
            if (x > threshold):
                gui.red_light.color('red')
                gui.green_light.color('grey')
                data.insert(col1, (str(splitstr[34 + inc1])))
                data.insert(col2, (str(x)))
            else:
                gui.red_light.color('grey')
                gui.green_light.color('green')
                data.insert(col1, '-')
                data.insert(col2, '-')
            inc1 += 56
            col1 += 1
            col2 += 1

        self.write_file(data)

        # function to write into the file

    def write_file(self, data):
        with open("Output.txt", "a") as text_file:
            text_file.write('\t'.join(data[0:]))
            text_file.write('\n')

if __name__ == '__main__':
    root = Tk()
    gui1 = GUI(root)
    rec_data = recv_data()
    root.mainloop()

Ошибка, которую я получаю:


Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
TypeError: getData() missing 1 required positional argument: 'self'

0 голосов
/ 09 июля 2020

Ошибка сообщает вам, что вы не можете использовать многопроцессорность для объекта, который включает виджеты tkinter. Вы пытаетесь использовать self.recvData в отдельном процессе. Это требует, чтобы self был маринован, чтобы его можно было отправить другому процессу. Однако python не может этого сделать, потому что он содержит виджеты tkinter, которые нельзя обработать.

Вам нужно будет переместить код, который выполняется в другом процессе, в отдельный класс, не содержащий виджетов tkinter.

...