在函数中定义全局变量并传递给类
有人能帮忙吗,
我想每隔x分钟从下面代码中定义的PROCESS类里取样数据(这个类会在其他未显示的函数调用时运行)。为了实现这个,我每隔X分钟运行一个调度函数,这个函数是由MAIN函数启动的,并由minmax_job函数执行。
但是我的minmax_job函数似乎不知道i的初始值。我尝试了很多次,想用全局变量之类的,但它还是不知道i = 0(一开始的值)。
i = 0
atc,otc,tssc = 0,0,0
atf,otf,tssf = False,False,False
class Process(threading.Thread):
def __init__(self, buffer3, broadcast_server):
threading.Thread.__init__(self)
self.setDaemon(True)
self.buffer3 = buffer3
self.factory = broadcast_server
def run(self):
today = datetime.now()
global time_of_last_run
global atv1,atv2,atv3,otv1,otv2,otv3,tssv1,tssv2,tssv3
global atf,otf,tssf
global atc,otc,tssc
if self.buffer3.startswith('kitchen aquarium: temp:'):
self.temp = self.buffer3.replace('kitchen aquarium: temp:','')
self.factory.broadcast("Aquarium temperature %s" % self.temp)
if atc == 1 and atf:
atv1 = float(self.temp)
atf = False
elif atc == 2 and atf:
atv2 = float(self.temp)
atf = False
elif atc == 3 and atf:
atv3 = float(self.temp)
atf = False
def minmax_job():
global atv1,atv2,atv3,otv1,otv2,otv3,tssv1,tssv2,tssv3
global atf,otf,tssf
global atc,otc,tssc,i
if i == 3:
i = 0
atc = 0
if i < 4:
atc = atc + 1
atf = True
i = i + 1
if __name__ == '__main__':
minmax_scheduler = Scheduler()
minmax_scheduler.add_interval_job(minmax_job, seconds=10)
minmax_scheduler.start()
2 个回答
@Pillmuncher 在上面的评论中提到的想法是对的,我来把它整理成一个完整的回答。你想通过全局变量在不同的进程或线程之间共享数据,但这种方法是非常不正确的。它可能有时候能工作,也可能不能,完全看运气,比如月亮的相位合适,或者你没有改变注释的位置等等。
原因比较复杂,但简单来说,你应该找一本计算机科学的操作系统教材,看看以下这些术语:
- 分叉(forking)
- 线程安全(thread safety)
- 多进程(multiprocessing)
- 受保护的内存(protected memory)
- 竞争条件(race condition)
- 消息队列(message queues)
- 进程间通信(interprocess communication)
- 线程锁(thread locks)
- 栈内存分配(stack memory allocation)
- 堆内存(heap memory)
在Python中,multiprocessing和threading模块提供了很多函数,可以用来声明共享内存并确保它的安全。你会喜欢安全的做法(即使你现在还不知道)。安全是好的,安全有时也可以(但并不总是)很快。
如果你试图用全局变量,而不是使用multiprocessing和threading模块的功能,你就像是在自杀:慢慢地、痛苦地,你会对生活感到厌倦。
所以,看看这个链接:http://docs.python.org/2/library/multiprocessing.html
里面有很多正确做法的例子。提前声明你的变量,把它们传递给每个线程或进程,过上你真正想要的正派生活。
一般来说,优先选择多进程。 多线程常常会遇到麻烦,虽然它可以更快,但你几乎不需要那种速度。那种速度伴随着危险和麻烦,需要花费大量的调试时间(现在和将来),而且你必须非常小心。最好还是像老一辈人(像我)那样:让多进程成为你的朋友,把多线程扔进[主要是微软相关的]垃圾堆里,别去碰它。
在这个例子中,i需要被声明为全局变量,然后在外部范围内赋值。
global i
i=0
def rabbit():
global i
print "rabbit ",i
#main here
if __name__ == '__main__':
rabbit()