2012-05-25 82 views
5

下面的代碼不掛在linux在Python 3.2.2做任何事情:爲什麼tkinter不能很好地處理多處理?

import tkinter 
from multiprocessing import Process 

def f(): 
    root = tkinter.Tk() 
    label = tkinter.Label(root) 
    label.pack() 
    root.mainloop() 

p = Process(target=f) 
p.start() 

我發現這個問題的唯一信息是issue 5527,其中值得注意的是,問題是tkinter之前被導入該進程是分叉的,可以通過在函數f中導入tkinter來解決該問題,並且問題發生在Linux而不是Solaris中。

有誰知道到底是什麼原因導致了這個問題,如果是故意的或最終會被修復?是否有任何解決方法,而不是在本地需要的地方導入tkinter(這看起來像不好的風格)?其他模塊是否有與多處理相似的問題?

+1

-0。你知道這個問題。你知道一個錯誤報告已經提交。您知道解決方法。唯一的另一個主要問題是「其他模塊是否有與多處理相似的問題?」,這似乎有點不確定。 –

+1

@StevenRumbalski:我不知道這個問題 - 我不知道tkinter在這裏無法正常工作,或者爲什麼它依賴於平臺。該錯誤報告是在3年前提交的,並且沒有跡象表明任何人都知道爲什麼(或者在什麼情況下)發生這種情況或者如何解決這個問題。也許我最後一個問題應該讀到「是否有任何其他標準庫模塊在分支進程之前無法導入」,這有點更具體。 – James

回答

0

我懷疑這個問題與連接到X服務器(通常是套接字)有關。如果這是在進程是fork() -ed之前創建的,那麼子進程將繼承此連接。但是如果它試圖使用它,X服務器會感到困惑。

Tkinter.py匆匆一瞥後,它看起來像在啓動過程可能是有用的,也許之前調用NoDefaultRoot功能。這一切都取決於連接到X服務器時。

否則在fork之後導入Tkinter似乎是要走的路。

0

截至2013年9月,還有一些關於錯誤報告的補充評論,可以更深入地瞭解實際問題。

http://bugs.python.org/issue5527#msg194848
http://bugs.python.org/issue5527#msg195480

基於上述,我猜像下面發生的事情:Tkinter的不是線程安全的,所以(無論何種原因)的Tkinter想知道哪個線程是主線程。 Tkinter假定Tkinter模塊加載時的主線程也是程序執行的主線程。當你在加載Tkinter之後進行分叉或者多進程時,這個假設被打破了。 (例如,叉後,記住的主線程在父母,而不是孩子。)