Python 和全局变量中的线程 - 数组和标准变量之间的区别?
Threading in Python and global variables - difference between arrays and standard variables?
我目前尝试使用线程编写更大的 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 未声明为全局变量。取消注释
global var
生成一个可执行脚本,两次打印 var 的值。
但是当使用numpy数组data_np时,没有声明
global data_np
需要。尽管如此,该脚本仍将 运行。
我不明白这种行为。有人可以解释一下吗?
global
用于允许分配给全局变量。如果没有这个声明,你可以读取一个没有被隐藏的全局变量。
看在上帝的份上,请不要这样做。阅读有关管理并发性的技术。
需要 global
语句来通知 Python 您希望变量(在本例中为 var
)被视为全局的、普遍可修改的名称而不是局部的每个函数的变量。如果将 var = 0
定义移到函数上方,您的情况会稍微好一些:
但是作为 ,"For the love of god don't do this." 绕过一些 NameError
s 并不是这里的关键问题。全局变量在很多程序中都很难管理,即使没有并发也是如此。在并发环境中,它们变成了噩梦。它们的行为在线程与多处理并发(两者都已导入,尽管您目前似乎正在使用线程)以及跨不同平台(Windows 与 Unix/Linux/Mac 工作方式不同)方面也非常不同OS X,例如)。
您的数组引用至少在某种程度上起作用的原因是全局结构(例如字典、列表、NumPy 数组)的内部内容很容易修改,即使整个结构不可修改。其中大部分与 Python 如何管理名称(粗略地说,"variables")有关,而与并发性关系不大。但是在并发环境中,对这些全局结构的修改很快就会变得冒险(读作:令人困惑、不可靠、不容易重现)。
所以,长话短说,在我们开始讨论 race condition 您的话题所面临的问题之前,这里很容易出现三四个重叠的问题。
如果您的 reader (child2
) 的睡眠时间比您的编写器 (child1
) 的睡眠时间长,您可能能够获得基本可用的代码。但要注意:除了玩具示例之外的任何东西,您都需要一个真正的并发感知结构(例如 a queue)。
我目前尝试使用线程编写更大的 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 未声明为全局变量。取消注释
global var
生成一个可执行脚本,两次打印 var 的值。 但是当使用numpy数组data_np时,没有声明
global data_np
需要。尽管如此,该脚本仍将 运行。 我不明白这种行为。有人可以解释一下吗?
global
用于允许分配给全局变量。如果没有这个声明,你可以读取一个没有被隐藏的全局变量。看在上帝的份上,请不要这样做。阅读有关管理并发性的技术。
需要 global
语句来通知 Python 您希望变量(在本例中为 var
)被视为全局的、普遍可修改的名称而不是局部的每个函数的变量。如果将 var = 0
定义移到函数上方,您的情况会稍微好一些:
但是作为 NameError
s 并不是这里的关键问题。全局变量在很多程序中都很难管理,即使没有并发也是如此。在并发环境中,它们变成了噩梦。它们的行为在线程与多处理并发(两者都已导入,尽管您目前似乎正在使用线程)以及跨不同平台(Windows 与 Unix/Linux/Mac 工作方式不同)方面也非常不同OS X,例如)。
您的数组引用至少在某种程度上起作用的原因是全局结构(例如字典、列表、NumPy 数组)的内部内容很容易修改,即使整个结构不可修改。其中大部分与 Python 如何管理名称(粗略地说,"variables")有关,而与并发性关系不大。但是在并发环境中,对这些全局结构的修改很快就会变得冒险(读作:令人困惑、不可靠、不容易重现)。
所以,长话短说,在我们开始讨论 race condition 您的话题所面临的问题之前,这里很容易出现三四个重叠的问题。
如果您的 reader (child2
) 的睡眠时间比您的编写器 (child1
) 的睡眠时间长,您可能能够获得基本可用的代码。但要注意:除了玩具示例之外的任何东西,您都需要一个真正的并发感知结构(例如 a queue)。