2017-02-09 63 views
3

此代碼執行在Linux上,但拋出一個AttributeError:類型的對象「T」對窗戶沒有屬性「VAL」,爲什麼呢?Python的多Linux窗口差異

from multiprocessing import Process 
import sys 

class T(): 
    @classmethod 
    def init(cls, val): 
     cls.val = val 

def f(): 
    print(T.val) 

if __name__ == '__main__': 
    T.init(5) 

    f() 

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

回答

2

Windows缺少一個fork()系統調用,它複製當前進程。這有很多含義,包括windows multiprocessing文檔頁面上列出的含義。更具體地講:

Bear in mind that if code run in a child process tries to access a global variable, then the value it sees (if any) may not be the same as the value in the parent process at the time that Process.start was called.

在內部,蟒蛇通過從頭開始一個新的進程,並告訴它再次加載所有模塊創建Windows上的新進程。因此,您在當前流程中所做的任何更改都不會被看到。

在你的榜樣,這意味着在子過程中,你的模塊將被載入,但if __name__ == '__main__'部分將不會運行。所以T.init將不會被調用,並且T.val將不存在,因此您看到的錯誤。

在另一方面,在POSIX系統(包括Linux)的,進程創建使用fork和全球所有的狀態保持不變。孩子運行一切的副本,所以它不必重新加載任何東西,並會看到它的副本T及其副本val

這也意味着,工藝創作是對POSIX系統資源,更快,更輕,尤其是在「複製」使用寫入時複製,以避免實際複製數據的開銷。

有使用多處理時其他怪癖,所有這些都在python multiprocessing guidelines詳述。

+0

'fork' vs'spawn'是一個很老的辯論。 NT內核一直有能力進行寫入時複製分支,但是從MS-DOS出來的Windows API本身不允許它。另外,在分叉多進程的過程中還存在一些不小的問題,在這種情況下,除了「fork」:「forkserver」和「spawn」之外,Python 3.4還爲您提供了兩個啓動選項。後者是Windows上唯一的選擇。 – eryksun

+1

確實如此。儘管NT內核中存在底層功能,但我始終發現在Win32中可以使用奇怪的無叉系統調用。我不禁要看到它,因爲微軟不願意屈服於舊的*「那些不懂Unix的人被指責重塑它」*說。哎呀,他們等到W2k8才加入符號鏈接。我準備好打賭,在未來的某些Windows版本中將會出現'fork()'等效,只是給他們一些時間。可能帶有一個名稱,如'DuplicateCurrentProcess'。 – spectras

+0

我的意思是不允許它是系統從在DOS上運行的Windows 2.0進化而來的方式,不會與'fork'一起工作 - 至少不會用於活動進程。內核模式Windows(win32k.sys)擴展了NT'EPROCESS'和'ETHREAD'結構,使'fork'可能會出現問題,比如死鎖。 OTOH,爲了分析一個過程,我們確實有能力發出惰性[快照](https://msdn.microsoft.com/en-us/library/dn457825)。 – eryksun