隨着友好dogcow說,在子進程中運行的功能,所有你需要做的正在使用multiprocessing.Process
:
p = multiprocessing.Process(target=f, args=('bob',))
p.start()
p.join()
當然,您可能想要在大多數*現實生活中使用的情況下,仍然會使用p
和join
。你顯然沒有通過產生一個新的過程來獲得任何平行度,只是爲了讓你的主要過程坐下來等待。
所以,你的情況,這只是:
p = multiprocessing.Process(target=self.Connection, args=(args1, args2))
但是這可能不會工作你的情況,因爲你想調用的方法當前self
對象。
首先,根據您的平臺和Python版本,multiprocessing
可能必須通過酸洗和通過管道發送綁定方法self.Connection
給孩子。這涉及酸洗self
實例以及該方法。所以它只會在MyFrame
對象被pickleable時才起作用。我很確定wx.Frame
不能被醃製。
即使你做得到self
對象的孩子,這顯然會副本,而不是一個共享實例。所以,當子進程的Connection
方法設置爲self.connection = …
時,這不會影響原始父進程的self
。
如果您嘗試調用任何wx.Frame
方法會更糟糕。即使所有的Python工作都在大多數平臺上工作,但試圖從錯誤的進程中修改GUI資源(如Windows)將不起作用。
您實際可以共享的唯一對象種類是您可以放入multiprocessing.Value
或multiprocessing.sharedctypes
的種類。
解決這個問題的辦法是分解出要childify到一個單獨的,孤立的函數的代碼,這股儘量少(最好什麼都沒有,或者只是一個Queue
or Pipe
)與父。
對於你的榜樣,這是很容易:
class Client(object):
def connect_and_fetch(self):
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.connection.connect(('192.0.1.135' , 3345))
while True:
data = self.connection.recv(1024)
if not data:
break
else:
print data
def do_client():
client = Client()
connect_and_fetch()
class MyFrame(wx.Frame):
# ...
def Connection(self):
self.child = multiprocessing.Process(target=do_client)
self.child.start()
# and now put a self.child.join() somewhere
事實上,你甚至不需要一個類的都在這裏,因爲你必須爲self
的唯一用途是存儲變量,可以很就像當地人一樣容易。但我在你的現實生活節目中猜測,還有更多的狀態。
在wxpython
wiki上有一個有趣(如果有點過時)的例子,稱爲MultiProcessing,它看起來像它做你想要什麼和更多。 (這是根據classmethod
子進程,而不是由於某種原因,一個獨立的功能,並使用舊式的語法,因爲它是老了,但我希望它仍然是有幫助的。)
如果您使用wx
對於您的GUI,您可能需要考慮使用其進程間機制,而不是本機Python。儘管在一般情況下它比較複雜且較不pythonic,但當您嘗試將子流程和通信管道集成到主事件循環中時,爲什麼不讓wx
處理它?
另一種方法是創建一個線程以等待子進程和/或其他任何Pipe
或Queue
您給它,然後創建並將wx.Event
s發佈到主線程。
*大多數不是全部。例如,如果f
暫時耗盡大量內存,則在子進程中運行它意味着儘可能快地將該內存釋放到操作系統。或者,如果它稱不好的第三方/遺留/任何具有令人討厭且文檔記錄不完整的全球副作用的代碼,則您將與這些副作用隔離開來。等等。
請多花點心思來解釋你的問題! – Moj 2013-05-03 18:06:57
你可能想在後臺*線程*(而不是子進程)中運行'Connection'並使用'wx.CallAfter()'向主線程(GUI)報告結果(參見[長時間運行的任務wiki] wiki.wxpython.org/LongRunningTasks))。 – jfs 2013-05-04 14:45:34