Python论坛  - 讨论区

标题:[python-chinese] 多线程如何共享变量

2007年11月13日 星期二 10:10

Cyril.Liu terry6394在gmail.com
星期二 十一月 13 10:10:24 HKT 2007

*我试图用一下的程序实现让一个线程运行5秒钟然后退出,但它没有这么做。*
*Python多线程中不能访问模块一级的变量?不解*

#-*-coding: utf-8 -*-
import time
from threading import Thread
global timeout
timeout = False
def count():
    i = 0
    while(not timeout):
        print i, timeout
        time.sleep(0.2)
        i += 1
def timer():
    print timeout
    time.sleep(5)
    timeout = True

if __name__ == "__main__":
    tCounter = Thread(target = count)
    tTimer = Thread(target = timer)
    tTimer.start()
    tCounter.start()

输出结果:

0 False
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.3/threading.py", line 436, in __bootstrap
    self.run()
  File "/usr/lib/python2.3/threading.py", line 416, in run
    self.__target(*self.__args, **self.__kwargs)
  File "threadingtest.py", line 17, in timer
    print timeout
UnboundLocalError: local variable 'timeout' referenced before assignment
1 False
2 False
3 False
4 False
5 False
6 False
7 False
8 False
9 False
。。。。。
。。。。。
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://python.cn/pipermail/python-chinese/attachments/20071113/2a9208a1/attachment.html 

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月13日 星期二 10:17

Leo Jay python.leojay在gmail.com
星期二 十一月 13 10:17:56 HKT 2007

On Nov 13, 2007 10:10 AM, Cyril. Liu <terry6394在gmail.com> wrote:
> 我试图用一下的程序实现让一个线程运行5秒钟然后退出,但它没有这么做。
> Python多线程中不能访问模块一级的变量?不解
>
> #-*-coding: utf-8 -*-
> import time
> from threading import Thread
> global timeout
> timeout = False
> def count():
>     i = 0
>     while(not timeout):
>         print i, timeout
>         time.sleep(0.2)
>         i += 1
> def timer():
>     print timeout
>     time.sleep(5)
>     timeout = True
>
> if __name__ == "__main__":
>     tCounter = Thread(target = count)
>     tTimer = Thread(target = timer)
>     tTimer.start()
>     tCounter.start()
>
>
> 输出结果:
>
> 0 False
> Exception in thread Thread-2:
> Traceback (most recent call last):
>   File "/usr/lib/python2.3/threading.py", line 436, in __bootstrap
>     self.run()
>   File "/usr/lib/python2.3/threading.py", line 416, in run
>     self.__target(*self.__args, **self.__kwargs)
>   File "threadingtest.py", line 17, in timer
>     print timeout
> UnboundLocalError: local variable 'timeout' referenced before assignment
> 1 False
> 2 False
> 3 False
> 4 False
> 5 False
> 6 False
> 7 False
> 8 False
> 9 False
> 。。。。。
> 。。。。。
>
>

在每个def的下面写global
如:
def count():
    global timeout




-- 
Best Regards,
Leo Jay

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月13日 星期二 11:46

Cyril.Liu terry6394在gmail.com
星期二 十一月 13 11:46:29 HKT 2007

的确每个加上global就好了。
不过我不理解Python的多线程共享变量的机制(或者是不理解模块级变量的机制),难道一定要变成全局变量才行吗?
大家给我解释一下. :D

On Nov 13, 2007 10:17 AM, Leo Jay <python.leojay at gmail.com> wrote:

> On Nov 13, 2007 10:10 AM, Cyril. Liu <terry6394 at gmail.com> wrote:
> > 我试图用一下的程序实现让一个线程运行5秒钟然后退出,但它没有这么做。
> > Python多线程中不能访问模块一级的变量?不解
> >
> > #-*-coding: utf-8 -*-
> > import time
> > from threading import Thread
> > global timeout
> > timeout = False
> > def count():
> >     i = 0
> >     while(not timeout):
> >         print i, timeout
> >         time.sleep(0.2)
> >         i += 1
> > def timer():
> >     print timeout
> >     time.sleep(5)
> >     timeout = True
> >
> > if __name__ == "__main__":
> >     tCounter = Thread(target = count)
> >     tTimer = Thread(target = timer)
> >     tTimer.start()
> >     tCounter.start()
> >
> >
> > 输出结果:
> >
> > 0 False
> > Exception in thread Thread-2:
> > Traceback (most recent call last):
> >   File "/usr/lib/python2.3/threading.py", line 436, in __bootstrap
> >     self.run()
> >   File "/usr/lib/python2.3/threading.py", line 416, in run
> >     self.__target(*self.__args, **self.__kwargs)
> >   File "threadingtest.py", line 17, in timer
> >     print timeout
> > UnboundLocalError: local variable 'timeout' referenced before assignment
> > 1 False
> > 2 False
> > 3 False
> > 4 False
> > 5 False
> > 6 False
> > 7 False
> > 8 False
> > 9 False
> > 。。。。。
> > 。。。。。
> >
> >
>
> 在每个def的下面写global
> 如:
> def count():
>    global timeout
>
>
>
>
> --
> Best Regards,
> Leo Jay
> _______________________________________________
> python-chinese
> Post: send python-chinese at lists.python.cn
> Subscribe: send subscribe to python-chinese-request at lists.python.cn
> Unsubscribe: send unsubscribe to  python-chinese-request at lists.python.cn
> Detail Info: http://python.cn/mailman/listinfo/python-chinese
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://python.cn/pipermail/python-chinese/attachments/20071113/42e83361/attachment.htm 

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月13日 星期二 12:10

Leo Jay python.leojay在gmail.com
星期二 十一月 13 12:10:13 HKT 2007

On Nov 13, 2007 11:46 AM, Cyril. Liu <terry6394在gmail.com> wrote:
> 的确每个加上global就好了。
> 不过我不理解Python的多线程共享变量的机制(或者是不理解模块级变量的机制),难道一定要变成全局变量才行吗?
> 大家给我解释一下. :D
>

这个不是多线程共享变量的机制的问题,是怎么使用全局变量的问题。呵呵。

一个全局变量,你要在某个函数中对它进行赋值的时候,一定要在函数的一开头用
global注明你要使用的是一个全局变量。就像你那个timer一样。是一定要写的。

不过,如果你不修改,只要读它的数据的话,是可以不写的,像那个count函数一样。
python在执行到使用timeout的地方时,在函数里没找到timeout的定义,就会自动到
global里去找。

不过,我个人的习惯是,如果要使用全局的变量的时候,都加上一个global的声明,
以防止出错。

-- 
Best Regards,
Leo Jay

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月13日 星期二 12:11

Jiahua Huang jhuangjiahua在gmail.com
星期二 十一月 13 12:11:23 HKT 2007

每个线程的函数都是独立调用的,

另外,注意有些变量的操作并不是原子的,
去看看 Queue 等线程安全的实现

在 07-11-13,Cyril. Liu<terry6394 at gmail.com> 写道:
> 的确每个加上global就好了。
> 不过我不理解Python的多线程共享变量的机制(或者是不理解模块级变量的机制),难道一定要变成全局变量才行吗?
> 大家给我解释一下. :D
>

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月13日 星期二 16:44

doudou doudou array.doudou在gmail.com
星期二 十一月 13 16:44:48 HKT 2007

嗯,我也是这个习惯,结果某次去面试时被鄙视了一下,对方说:这个语句多余。

在 07-11-13,Leo Jay<python.leojay在gmail.com> 写道:
> On Nov 13, 2007 11:46 AM, Cyril. Liu <terry6394在gmail.com> wrote:
> > 的确每个加上global就好了。
> > 不过我不理解Python的多线程共享变量的机制(或者是不理解模块级变量的机制),难道一定要变成全局变量才行吗?
> > 大家给我解释一下. :D
> >
>
> 这个不是多线程共享变量的机制的问题,是怎么使用全局变量的问题。呵呵。
>
> 一个全局变量,你要在某个函数中对它进行赋值的时候,一定要在函数的一开头用
> global注明你要使用的是一个全局变量。就像你那个timer一样。是一定要写的。
>
> 不过,如果你不修改,只要读它的数据的话,是可以不写的,像那个count函数一样。
> python在执行到使用timeout的地方时,在函数里没找到timeout的定义,就会自动到
> global里去找。
>
> 不过,我个人的习惯是,如果要使用全局的变量的时候,都加上一个global的声明,
> 以防止出错。
>
> --
> Best Regards,
> Leo Jay
> _______________________________________________
> python-chinese
> Post: send python-chinese在lists.python.cn
> Subscribe: send subscribe to python-chinese-request在lists.python.cn
> Unsubscribe: send unsubscribe to  python-chinese-request在lists.python.cn
> Detail Info: http://python.cn/mailman/listinfo/python-chinese

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月14日 星期三 17:57

swordsp sparas2006在gmail.com
星期三 十一月 14 17:57:36 HKT 2007

除去global的问题,以多线程环境来说,这个程序其实是不安全的。
对非只读(mutable)共享变量的任何非原子操作序列(包括需要维护一致性的相关操作,可以用"事务"来理解)都需要锁机制才能保证同步。
以这里为例,timeout显然是一个mutable的共享变量,但:
*print i, timeout*
这一句就不是原子操作,可能会print到一半的时候线程切换,然后timeout的值被改变,这样就破坏了语义上的一致性。

关于线程同步问题,这篇文章讲解得比较完整:
http://effbot.org/zone/thread-synchronization.htm
On Nov 13, 2007 11:46 AM, Cyril. Liu <terry6394 at gmail.com> wrote:

> 的确每个加上global就好了。
> 不过我不理解Python的多线程共享变量的机制(或者是不理解模块级变量的机制),难道一定要变成全局变量才行吗?
> 大家给我解释一下. :D
>
>
> On Nov 13, 2007 10:17 AM, Leo Jay <python.leojay at gmail.com > wrote:
>
> >  On Nov 13, 2007 10:10 AM, Cyril. Liu < terry6394 at gmail.com> wrote:
> > > 我试图用一下的程序实现让一个线程运行5秒钟然后退出,但它没有这么做。
> > > Python多线程中不能访问模块一级的变量?不解
> > >
> > > #-*-coding: utf-8 -*-
> > > import time
> > > from threading import Thread
> > > global timeout
> > > timeout = False
> > > def count():
> > >     i = 0
> > >     while(not timeout):
> > >         print i, timeout
> > >         time.sleep(0.2)
> > >         i += 1
> > > def timer():
> > >     print timeout
> > >     time.sleep(5)
> > >     timeout = True
> > >
> > > if __name__ == "__main__":
> > >     tCounter = Thread(target = count)
> > >     tTimer = Thread(target = timer)
> > >     tTimer.start()
> > >     tCounter.start()
> > >
> > >
> > > 输出结果:
> > >
> > > 0 False
> > > Exception in thread Thread-2:
> > > Traceback (most recent call last):
> > >   File "/usr/lib/python2.3/threading.py", line 436, in __bootstrap
> > >     self.run()
> > >   File "/usr/lib/python2.3/threading.py", line 416, in run
> > >     self.__target(*self.__args, **self.__kwargs)
> > >   File "threadingtest.py", line 17, in timer
> > >     print timeout
> > > UnboundLocalError: local variable 'timeout' referenced before
> > assignment
> > > 1 False
> > > 2 False
> > > 3 False
> > > 4 False
> > > 5 False
> > > 6 False
> > > 7 False
> > > 8 False
> > > 9 False
> > > 。。。。。
> > > 。。。。。
> > >
> > >
> >
> > 在每个def的下面写global
> > 如:
> > def count():
> >    global timeout
> >
> >
> >
> >
> > --
> > Best Regards,
> > Leo Jay
> > _______________________________________________
> > python-chinese
> > Post: send python-chinese at lists.python.cn
> > Subscribe: send subscribe to python-chinese-request at lists.python.cn
> > Unsubscribe: send unsubscribe to  python-chinese-request at lists.python.cn
> > Detail Info: http://python.cn/mailman/listinfo/python-chinese
>
>
>
> _______________________________________________
> python-chinese
> Post: send python-chinese at lists.python.cn
> Subscribe: send subscribe to python-chinese-request at lists.python.cn
> Unsubscribe: send unsubscribe to  python-chinese-request at lists.python.cn
> Detail Info: http://python.cn/mailman/listinfo/python-chinese
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://python.cn/pipermail/python-chinese/attachments/20071114/a6384040/attachment-0001.html 

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月14日 星期三 18:12

Jiahua Huang jhuangjiahua在gmail.com
星期三 十一月 14 18:12:31 HKT 2007

所以说请参考 Queue 等线程安全的数据结构

在 07-11-14,swordsp<sparas2006 at gmail.com> 写道:
> 除去global的问题,以多线程环境来说,这个程序其实是不安全的。

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月14日 星期三 19:14

Cyril.Liu terry6394在gmail.com
星期三 十一月 14 19:14:08 HKT 2007

  File "threadingtest.py", line 17, in timer
    print timeout
UnboundLocalError: local variable 'timeout' referenced before assignment

这段错误信息来看,print我也只是对timeout变量做一个读操作而已,按你的说法,"只要读它的数据的话,是可以不写" 这个地方是不会报错的啊。
另外从报错的信息来看 "local variable 'timeout' referenced before assignment"
系统认为timeout没有定义。对于被多线程执行的函数来说是不在模块这个作用域内的呢?因为假设timer这个方法是模块内不通过threading来执行,是不会有任何问题的。
不知道可否这样理解Python解释器在通过threading.Thread
()创建线程对象的时候只是把timer方法引用到了Thread类中,没有做其他的处理。

On Nov 13, 2007 12:10 PM, Leo Jay <python.leojay at gmail.com> wrote:

> On Nov 13, 2007 11:46 AM, Cyril. Liu <terry6394 at gmail.com> wrote:
> > 的确每个加上global就好了。
> > 不过我不理解Python的多线程共享变量的机制(或者是不理解模块级变量的机制),难道一定要变成全局变量才行吗?
> > 大家给我解释一下. :D
> >
>
> 这个不是多线程共享变量的机制的问题,是怎么使用全局变量的问题。呵呵。
>
> 一个全局变量,你要在某个函数中对它进行赋值的时候,一定要在函数的一开头用
> global注明你要使用的是一个全局变量。就像你那个timer一样。是一定要写的。
>
> 不过,如果你不修改,只要读它的数据的话,是可以不写的,像那个count函数一样。
> python在执行到使用timeout的地方时,在函数里没找到timeout的定义,就会自动到
> global里去找。
>
> 不过,我个人的习惯是,如果要使用全局的变量的时候,都加上一个global的声明,
> 以防止出错。
>
> --
> Best Regards,
> Leo Jay
> _______________________________________________
> python-chinese
> Post: send python-chinese at lists.python.cn
> Subscribe: send subscribe to python-chinese-request at lists.python.cn
> Unsubscribe: send unsubscribe to  python-chinese-request at lists.python.cn
> Detail Info: http://python.cn/mailman/listinfo/python-chinese
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://python.cn/pipermail/python-chinese/attachments/20071114/a1dd13c6/attachment.htm 

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月14日 星期三 20:50

Leo Jay python.leojay在gmail.com
星期三 十一月 14 20:50:13 HKT 2007

On Nov 14, 2007 7:14 PM, Cyril. Liu <terry6394在gmail.com> wrote:
>   File "threadingtest.py", line 17, in timer
>     print timeout
> UnboundLocalError: local variable 'timeout' referenced before assignment
>
> 这段错误信息来看,print我也只是对timeout变量做一个读操作而已,按你的说法,"只要读它的数据的话,是可以不写" 这个地方是不会报错的啊。

这里是在读,可是,你下面有写的操作啊。就是timeout = True那句。
不信你把这句去掉看看。

> 另外从报错的信息来看 "local variable 'timeout' referenced before assignment"
> 系统认为timeout没有定义。对于被多线程执行的函数来说是不在模块这个作用域内的呢?因为假设timer这个方法是模块内不通过threading来执行,是不会有任何问题的。
> 不知道可否这样理解Python解释器在通过threading.Thread()创建线程对象的时候只是把timer方法引用到了Thread类中,没有做其他的处理。
>
>

你这种说法不对,在同一个进程中的全局变量是谁都可以访问的。跟线程没关系。

-- 
Best Regards,
Leo Jay

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月15日 星期四 13:24

李昆仑 jackyboy在163.com
星期四 十一月 15 13:24:31 HKT 2007

doudou doudou,您好!

	  我的理解是:
如果要对一个全局变量赋值,那么应该用 global声明一下,否则就不是必要的

刚开始学python,不知道这样对否?


======= 2007-11-13 16:45:35 您在来信中写道:=======

>嗯,我也是这个习惯,结果某次去面试时被鄙视了一下,对方说:这个语句多余。
>
>在 07-11-13,Leo Jay<python.leojay在gmail.com> 写道:
>> On Nov 13, 2007 11:46 AM, Cyril. Liu <terry6394在gmail.com> wrote:
>> > 的确每个加上global就好了。
>> > 不过我不理解Python的多线程共享变量的机制(或者是不理解模块级变量的机制),难道一定要变成全局变量才行吗?
>> > 大家给我解释一下. :D
>> >
>>
>> 这个不是多线程共享变量的机制的问题,是怎么使用全局变量的问题。呵呵。
>>
>> 一个全局变量,你要在某个函数中对它进行赋值的时候,一定要在函数的一开头用
>> global注明你要使用的是一个全局变量。就像你那个timer一样。是一定要写的。
>>
>> 不过,如果你不修改,只要读它的数据的话,是可以不写的,像那个count函数一样。
>> python在执行到使用timeout的地方时,在函数里没找到timeout的定义,就会自动到
>> global里去找。
>>
>> 不过,我个人的习惯是,如果要使用全局的变量的时候,都加上一个global的声明,
>> 以防止出错。
>>
>> --
>> Best Regards,
>> Leo Jay
>> _______________________________________________
>> python-chinese
>> Post: send python-chinese在lists.python.cn
>> Subscribe: send subscribe to python-chinese-request在lists.python.cn
>> Unsubscribe: send unsubscribe to  python-chinese-request在lists.python.cn
>> Detail Info: http://python.cn/mailman/listinfo/python-chinese
>_______________________________________________
>python-chinese
>Post: send python-chinese在lists.python.cn
>Subscribe: send subscribe to python-chinese-request在lists.python.cn
>Unsubscribe: send unsubscribe to  python-chinese-request在lists.python.cn
>Detail Info: http://python.cn/mailman/listinfo/python-chinese

= = = = = = = = = = = = = = = = = = = =
			

        致
礼!
 
				 
        李昆仑
        jackyboy在163.com
          2007-11-15


[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

2007年11月18日 星期日 15:20

doudou doudou array.doudou在gmail.com
星期日 十一月 18 15:20:51 HKT 2007

呵呵,很对的

[导入自Mailman归档:http://www.zeuux.org/pipermail/zeuux-python]

如下红色区域有误,请重新填写。

    你的回复:

    请 登录 后回复。还没有在Zeuux哲思注册吗?现在 注册 !

    Zeuux © 2025

    京ICP备05028076号