简体   繁体   English

tkinter多处理泡菜错误

[英]tkinter multiprocessing pickle error

In Python 2.7.11. 在Python 2.7.11中。 I have a tkinter GUI where the user enters files into a Listbox. 我有一个tkinter GUI,用户可以在其中将文件输入到列表框中。 The RUN button is supposed to read each file and insert data into a database. 应该使用RUN按钮读取每个文件并将数据插入数据库。 I need the reading to be in series, not parallel. 我需要阅读的内容是串联的,而不是平行的。 I want to run the reading in a separate process. 我想在一个单独的过程中运行阅读。 I ran the following code outside of tkinter, as a test, and I got the desired results... The main thread appears to finish while the reader is still chugging along in the background. 我在tkinter外部运行了以下代码作为测试,并且得到了预期的结果...当读者仍然在后台徘徊时,主线程似乎完成了。

import multiprocessing as mp
import time
import F06


def _worker(li):
    for path in li:
    print('worker is processing:={}'.format(path))
    reader = F06.Reader()
    reader.read_sol_106(path)
    time.sleep(0.5)
    print('process complete')

if __name__ == '__main__':

    # make a list of files to read
    li = [
    'Results/1201301__SOL106.f06',
    'Results/1201302__SOL106.f06',
    'Results/1201303__SOL106.f06',
    ]
    p = mp.Process(target=_worker, args=(li,))
    p.start()
    print('main thread finished')

I tried adding the code in a similar fashion to my tkinter program and I cannot get it to run. 我试图以类似的方式将代码添加到我的tkinter程序中,但我无法使其运行。 The tkinter GUI is in a class, not sure if this is contributing to the problem, just FYI. tkinter GUI在一个类中,不确定这是否是导致问题的原因,只是FYI。 This is the following error feedback: 这是以下错误反馈:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1537, in __call__
    return self.func(*args)
  File "C:\Users\00835182\Documents\METHODS\01_PET_PROJECTS\13_Py_SQL\DB_GUI.py", line 122, in run
    p.start()
  File "C:\Python27\lib\multiprocessing\process.py", line 130, in start
    self._popen = Popen(self)
  File "C:\Python27\lib\multiprocessing\forking.py", line 277, in __init__
    dump(process_obj, to_child, HIGHEST_PROTOCOL)
  File "C:\Python27\lib\multiprocessing\forking.py", line 199, in dump
    ForkingPickler(file, protocol).dump(obj)
  File "C:\Python27\lib\pickle.py", line 224, in dump
    self.save(obj)
  File "C:\Python27\lib\pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Python27\lib\pickle.py", line 425, in save_reduce
    save(state)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 655, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 687, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\multiprocessing\forking.py", line 67, in dispatcher
    self.save_reduce(obj=obj, *rv)
  File "C:\Python27\lib\pickle.py", line 401, in save_reduce
    save(args)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 554, in save_tuple
    save(element)
  File "C:\Python27\lib\pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Python27\lib\pickle.py", line 425, in save_reduce
    save(state)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 655, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 687, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 731, in save_inst
    save(stuff)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 655, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 687, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 731, in save_inst
    save(stuff)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 655, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 687, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 731, in save_inst
    save(stuff)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 655, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 687, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 655, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 687, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 731, in save_inst
    save(stuff)
  File "C:\Python27\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python27\lib\pickle.py", line 655, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python27\lib\pickle.py", line 687, in _batch_setitems
    save(v)
  File "C:\Python27\lib\pickle.py", line 313, in save
    (t.__name__, obj))
PicklingError: Can't pickle 'tkapp' object: <tkapp object at 0x024932F0>
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Python27\lib\multiprocessing\forking.py", line 381, in main
    self = load(from_parent)
  File "C:\Python27\lib\pickle.py", line 1384, in load
    return Unpickler(file).load()
  File "C:\Python27\lib\pickle.py", line 864, in load
    dispatch[key](self)
  File "C:\Python27\lib\pickle.py", line 886, in load_eof
    raise EOFError
EOFError

I am not sure, but the problem my lie in the 'self' argument. 我不确定,但是问题出在“自我”论点上。 My code, at least what I think are the relevant portions are: 我的代码,至少我认为相关的部分是:

def run(self):  # ... linked to "Run" button 'command'
    f06_files = self.frame_2_listbox.get(0, 'end')  # ............. get List of results files
    p = multiprocessing.Process(target=self._run, args=(f06_files,))
    # this also did not work
    # p = multiprocessing.Process(target=self._run, args=(None, f06_files))
    p.start()

def _run(self, li):
    num_files = len(li)  # ........................................ total number of file
    file_counter = 0  # ........................................... file counter

    for path in li:  # ............................................ iterate over files

        file_counter += 1  # ...................................... increment file counter
        s = 'File  {}  of  {}'.format(file_counter, num_files)  # . string msg to user
        print(s)

        # read the results file
        reader = Reader()  # ...................................... instantiate Reader, clears for reuse
        reader.read_sol_106(path)  # .............................. read results file, extract loads

        # retrieve loads
        bars = reader.get_bar_forces()  # ......................... List of Tuples
        beams = reader.get_beam_forces()  # .......................
        bushs = reader.get_bush_forces()  # .......................
        cons = reader.get_con_forces()  # .........................
        rods = reader.get_rod_forces()  # .........................
        shells = reader.get_shell_forces()  # .....................
        gaps = reader.get_gap_forces()  # .........................
        springs = reader.get_spring_forces()  # ...................

        # insert loads into database
        self.insert_data(file=path, bars=bars, beams=beams, bushs=bushs, cons=cons, rods=rods, shells=shells, gaps=gaps, springs=springs)

I'm ready to learn whatever you can teach me. 我准备学习任何可以教给我的知识。

Instead of using the multiprocessing module, which calls Popen, try using Popen directly (I dont know if this will work, but its worth a shot). 与其使用调用Popen的多处理模块,不如直接使用Popen(我不知道这是否可行,但是值得一试)。 This method shouldnt cause the call to pickle to happen. 该方法不应导致腌制的调用发生。

In a separate file named worker.py 在名为worker.py的单独文件中

import time
import F06
import sys
import argparse

if sys.argc == 0:
    sys.exit(1)

for path in sys.argv:
    print('worker is processing:={}'.format(path))
    reader = F06.Reader()
    reader.read_sol_106(path)
    time.sleep(0.5)
    print('process complete')

Then in the main file. 然后在主文件中。

from subprocess import Popen, PIPE

if __name__ == '__main__':

    # make a list of files to read
    cmd = [
        'python',
        'worker.py',
        'Results/1201301__SOL106.f06',
        'Results/1201302__SOL106.f06',
        'Results/1201303__SOL106.f06',
    ]
    p = Popen(cmd, stderr=PIPE, stdout=PIPE)
    out, err = p.communicate()
    print('main thread finished')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM