tkinter多处理pickle错误

时间:2017-12-11 23:58:59

标签: python tkinter multiprocessing

在Python 2.7.11中。我有一个tkinter GUI,用户将文件输入到列表框中。 RUN按钮应该读取每个文件并将数据插入数据库。我需要读数是串联的,而不是平行的。我想在一个单独的过程中运行阅读。我在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')

我尝试以与我的tkinter程序类似的方式添加代码,但我无法运行它。 tkinter GUI在一个类中,不确定这是否导致问题,仅仅是FYI。这是以下错误反馈:

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

我不确定,但问题在于我在“自我”论证中的谎言。我的代码,至少我认为的相关部分是:

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)

我已准备好学习你能教给我的任何东西。

1 个答案:

答案 0 :(得分:1)

不使用调用Popen的多处理模块,而是直接尝试使用Popen(我不知道这是否可行,但值得一试)。这种方法不应该导致调用pickle发生。

在名为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')

然后在主文件中。

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')