2017-08-04 38 views
0

我創建了一個tkinter文本小部件,並且我想將sys.stdout重定向到文本小部件。我部分地完成了這個功能,但是我面臨着多處理的問題。如何重定向多處理池功能

下面是一個Python 3的玩具,你可以玩,

import sys 
import tkinter as tk 
from multiprocessing import Pool 

root = tk.Tk() 
root.geometry('600x400+30+30') 

textArea = tk.Text(root, bg='gray', width=70, height=20) 
textArea.pack() 
tk.Button(root, text='click me', command=lambda: print('Dont touch\n me!')).pack() 

class redirectStd(): 
    def __init__(self, textWidget): 
     self.textBoard = textWidget 
     self.flush = sys.stdout.flush 
    def write(self, msg): 
     self.textBoard.insert('end', msg) 

sys.stdout = redirectStd(textArea) 
sys.stderr = redirectStd(textArea) 

def f(x): 
    print('calculate:', x, '** 2') 
    return x ** 2 

def testParallel(): 
    print('start testing') 
    with Pool(processes=2) as p: 
     res = p.map(f, [1, 4, 0, 7, 3, 5]) 
     print(res) 

tk.Button(root, text='test multiprocessing', command=testParallel).pack() 

root.mainloop() 

這將正常運行。但是,def f(x)中的打印將不會打印文本小部件中的任何內容。

如果class redirectStd塊註釋self.flush = sys.stdout.flush,會導致錯誤,抱怨沖洗redirectStd不確定的。在這個階段,我還沒有找到如何定義沖洗方法redirectStd。完整的錯誤消息是

start testing 
Exception in Tkinter callback 
Traceback (most recent call last): 
    File "/Users/zsf/miniconda3/lib/python3.6/tkinter/__init__.py", line 1699, in __call__ 
    return self.func(*args) 
    File "test.py", line 28, in testParallel 
    with Pool(processes=2) as p: 
    File "/Users/zsf/miniconda3/lib/python3.6/multiprocessing/context.py", line 119, in Pool 
    context=self.get_context()) 
    File "/Users/zsf/miniconda3/lib/python3.6/multiprocessing/pool.py", line 168, in __init__ 
    self._repopulate_pool() 
    File "/Users/zsf/miniconda3/lib/python3.6/multiprocessing/pool.py", line 233, in _repopulate_pool 
    w.start() 
    File "/Users/zsf/miniconda3/lib/python3.6/multiprocessing/process.py", line 105, in start 
    self._popen = self._Popen(self) 
    File "/Users/zsf/miniconda3/lib/python3.6/multiprocessing/context.py", line 277, in _Popen 
    return Popen(process_obj) 
    File "/Users/zsf/miniconda3/lib/python3.6/multiprocessing/popen_fork.py", line 17, in __init__ 
    sys.stdout.flush() 
AttributeError: 'redirectStd' object has no attribute 'flush' 

任何人都可以提供一個解決這個問題的提示嗎?謝謝!

+1

重新思考你的方法,使用一些_ ** IPC ** _而不是重定向。你的基本問題是'f'是一個單獨的進程,並有他自己的'Stdout。 – stovfl

回答

0

我認爲你正在使用多線程的方式可能有問題,看看下面

https://docs.python.org/2/library/multiprocessing.html https://docs.python.org/2/library/multiprocessing.html#multiprocessing-programming

我在一個稍微不同的方式計算出你的問題的文件,希望這有助於

import sys 
import tkinter as tk 
from multiprocessing import Pool 


class redirectStd(): 
    def __init__(self, textWidget): 
    self.textBoard = textWidget 
    #self.flush = sys.stdout.flush 
def write(self, msg): 
    self.textBoard.insert('end', msg) 

def f(x): 
    print('calculate:', x, '** 2') 
    return x ** 2 

if __name__ == '__main__': 

    root = tk.Tk() 
    root.geometry('600x400+30+30') 

    textArea = tk.Text(root, bg='gray', width=70, height=20) 
    textArea.pack() 
    tk.Button(root, text='click me', command=lambda: print('Dont touch\n me!')).pack() 

    sys.stdout = redirectStd(textArea) 
    sys.stderr = redirectStd(textArea) 

    def testParallel(): 
     p = Pool(5) 
     print(p.map(f, [10, 2, 3])) 

    tk.Button(root, text='test multiprocessing', command=testParallel).pack() 

    root.mainloop() 
+0

感謝您的解決方案。它仍然導致該錯誤。我必須取消註釋'#self.flush = sys.stdout.flush'才能正確運行。但是,print('calculate:',x,'** 2')不打印任何東西。你有任何進一步的建議嗎?順便說一下,我測試這個macOS 10.12.6 –