2015-07-21 139 views
-1

我目前嘗試使用線程編寫一個更大的python程序,並遇到了數組不必被聲明爲全局的問題。Python中的線程和全局變量 - 數組和標準變量之間的區別?

import numpy as np 
import threading 
import time 
import ctypes 
import multiprocessing 
import random 
import os 


def child1(): 
    #global var 
    starttime = time.time() 
    for ite in range(10): 
     #data_np[ite] = time.time()-starttime 
     #print data_np[ite] 
     var += 1 
     print var 
     time.sleep(1) 

def child2(): 
    #global var 
    for ite in range(10): 
     #print data_np 
     print var 
     print "\n" 
     time.sleep(1) 


os.system("clear") 
data_np = np.zeros(shape=(10), dtype="float") 
var = 0 

thread1 = threading.Thread(target=child1) 
thread2 = threading.Thread(target=child2) 

thread1.start() 
thread2.start() 

thread1.join() 
thread2.join() 

由於var未被聲明爲全局變量,因此上述代碼將產生錯誤消息。 Unnotement

global var 

產生一個可執行腳本,打印var的值兩次。 但是用numpy的陣列data_np,沒有聲明需要

global data_np 

時。腳本將運行。 我不明白這種行爲。有人可以對此作出解釋嗎?

回答

0

global陳述要求通知的Python你想要一個變量(var在這種情況下)被視爲一個全球性的,普遍的修改名稱,而不是爲每個函數的局部變量。如果您將var = 0的定義移到以上功能上,您的票價會稍微好一些:

但是由於Marcin says「對於上帝的愛不要這樣做」。避開幾個NameError這裏並不是關鍵問題。全局變量在很多程序中很難管理,即使沒有併發性。在併發環境中,他們變成了噩夢。它們在線程和多處理併發性(您已經導入了兩者,儘管目前似乎使用線程)以及跨不同平臺(Windows的工作方式與Unix/Linux/Mac OS X不同,例如, )。

至少在某種程度上,數組引用起作用的原因是全局結構(例如字典,列表,NumPy數組)的內部內容即使在整個結構不是時也是可以修改的。其中大部分與Python如何管理名稱(粗略地說是「變量」)有關,而與併發性無關。但是在一個併發環境中,對這些全局結構的修改會非常迅速地變得非常危險(閱讀:令人困惑,不可靠,不容易重現)。

因此,長話短說,在我們甚至開始討論您的主題所面臨的race condition之前,這裏很容易出現三到四個重疊問題。

如果您的閱讀器(child2)的睡眠時間比您的作者(child1)長,您可能可以獲得基本工作代碼。但要小心:除了一個玩具的例子,你需要一個真正的併發感知結構(例如a queue)。

+0

謝謝你的回答!它爲底層結構提供了一個很好的第一見解。 – kM00n

+0

也許爲了使事情更清楚,代碼只是一個例子,以澄清我遇到的數組和標準變量被區別對待的問題。在我的主程序中,我想要創建兩個進程,一個進行繪圖,另一個進程包含兩個線程。一個用於與外部設備通信的線程,另一個用於處理用戶輸入。我嘗試通過僅分別向一個進程或線程寫入變量或數組來避免併發性。到目前爲止,這在OSX下得到了解決。 – kM00n

+0

是的。如果你只從一個線程寫入結構,這大大簡化了事情。由於「競賽條件」,這並不意味着你會得到100%可靠的結果。對於這些,你需要真正的併發感知結構,比如隊列。對於簡單的示範,你有時可以不使用它們。 –

0
  1. global用於允許分配給全局變量。沒有這個聲明,你可以讀取一個沒有被遮蔽的全局變量。

  2. 對於上帝的愛不要這樣做。閱讀有關管理併發的技巧。