【问题标题】:ForkingPickler(file, protocol).dump(obj) TypeError: cannot pickle '_tkinter.tkapp' objectForkingPickler(file, protocol).dump(obj) TypeError: cannot pickle '_tkinter.tkapp' object
【发布时间】:2020-07-09 23:07:36
【问题描述】:

下面是我的代码,我的函数从服务器接收数据块并将它们放入 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

谁能告诉我这里到底哪里出错了?

【问题讨论】:

    标签: python tkinter multiprocessing queue


    【解决方案1】:

    错误告诉您不能对包含 tkinter 小部件的对象使用多处理。您正在尝试在单独的进程中使用 self.recvData。这需要对self 进行腌制,以便将其发送到其他进程。但是,python 不能这样做,因为它包含无法腌制的 tkinter 小部件。

    您需要将在另一个进程中运行的代码移动到不包含任何 tkinter 小部件的单独类中。

    【讨论】:

    • 您的意思是说我应该将recvData 代码移动到另一个类?我还应该将calculate_threshold 代码移到另一个类吗?
    • @Newbie:是的,就像答案说的那样,您需要将在另一个进程中运行的代码移动到一个单独的类中。
    • 抱歉,这是一个非常愚蠢的问题。所以我将getDatarecvDatacalculate_thresholdwrite_file 移动到另一个类,并在 if name == 'main 中创建了 GUI 类和新类的两个对象'。现在我不确定如何从其他类调用类的函数。不确定我是否做得对。我将代码添加为帖子
    【解决方案2】:

    创建新类后代码更改:

    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'
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-09-24
      • 2021-12-25
      • 2020-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多