● 先执行最基本的串行执行,从开始到结束可以看到task1先执行,然后是task2,再然后main函数执行结束,总共耗时10s
#coding = utf-8
from time import ctime,time,sleep
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(2)
if __name__ == '__main__':
task1(2)
task2(2)
print ('Main Function End %s' % ctime())
● 打印结果
● root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 19:51:08 2016
Func1 Task --- No.1 start at Sat Aug 13 19:51:11 2016
Func2 Task --- No.0 start at Sat Aug 13 19:51:14 2016
Func2 Task --- No.1 start at Sat Aug 13 19:51:16 2016
Main Function End Sat Aug 13 19:51:18 2016
● 进阶版
引入threading.Thread,用两个线程进行程序执行
#coding = utf-8
import threading
from time import ctime,time,sleep
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(2)
if __name__ == '__main__':
t1 = threading.Thread(target = task1, args = (2,))
t2 = threading.Thread(target = task2, args = (2,))
t1.start()
t2.start()
print ('Main Function End\t %s' % ctime())
执行结果
root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 20:36:49 2016
Func2 Task --- No.0 start at Sat Aug 13 20:36:49 2016
Main Function End Sat Aug 13 20:36:49 2016
Func2 Task --- No.1 start at Sat Aug 13 20:36:51 2016
Func1 Task --- No.1 start at Sat Aug 13 20:36:52 2016
● 接下来观察一下daemon参数起什么作用
设置线程进行setDaemon()操作,讲daemon参数设置为True如下,观察结果:
#coding = utf-8
import threading
from time import ctime,time,sleep
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(2)
if __name__ == '__main__':
t1 = threading.Thread(target = task1, args = (2,))
t2 = threading.Thread(target = task2, args = (2,))
t1.setDaemon(True)
t2.setDaemon(True)
t1.start()
t2.start()
print ('Main Function End\t %s' % ctime())
这里需要注意的是,threading.Thread设置daemon参数必须在start()之前,不然程序会被无限挂起
root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 20:45:20 2016
Main Function End Sat Aug 13 20:45:20 2016
Func2 Task --- No.0 start at Sat Aug 13 20:45:20 2016
由此可见,t.setDaemon(True)的结果是:主线程在线程t结束之前就会随着主线程的结束而kill掉线程t,程序结束。
● 再玩一次:
#coding = utf-8
import threading
from time import ctime,time,sleep
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(5)
if __name__ == '__main__':
t1 = threading.Thread(target = task1, args = (2,))
t2 = threading.Thread(target = task2, args = (2,))
t1.setDaemon(False)
t2.setDaemon(True)
t1.start()
t2.start()
print ('Main Function End\t %s' % ctime())
● 那这样的话我就搞不懂了,为什么task2的第二条语句还是能打印出来?很令人费解……
由此推测setDaemon的作用是针对主线程的,用来设置主线程在执行完之后不能直接退出程序。
root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 21:03:57 2016
Func2 Task --- No.0 start at Sat Aug 13 21:03:57 2016
Main Function End Sat Aug 13 21:03:57 2016
Func1 Task --- No.1 start at Sat Aug 13 21:04:00 2016
Func2 Task --- No.1 start at Sat Aug 13 21:04:02 2016
通过以上执行结果,我们得知Python默认的daemon参数是False的,主线程会等到子线程执行完毕之后才会杀掉子线程结束程序。
● 故意将setDaemon放到start后面进行观察
#coding = utf-8
import threading
from time import ctime,time,sleep
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(2)
if __name__ == '__main__':
t1 = threading.Thread(target = task1, args = (2,))
t2 = threading.Thread(target = task2, args = (2,))
t1.start()
t2.start()
t1.setDaemon(False)
t2.setDaemon(True)
print ('Main Function End\t %s' % ctime())
执行结果如下:
root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 20:50:26 2016
Func2 Task --- No.0 start at Sat Aug 13 20:50:26 2016
Traceback (most recent call last):
File "threading_test.py", line 20, in <module>
t1.setDaemon(False)
File "/usr/lib/python2.7/threading.py", line 1036, in setDaemon
self.daemon = daemonic
File "/usr/lib/python2.7/threading.py", line 1029, in daemon
raise RuntimeError("cannot set daemon status of active thread");
RuntimeError: cannot set daemon status of active thread
Func2 Task --- No.1 start at Sat Aug 13 20:50:28 2016
Func1 Task --- No.1 start at Sat Aug 13 20:50:29 2016
瞧,主线程没有打印结果
● 加入join()观察一下结果:
#coding = utf-8
import threading
from time import ctime,time,sleep
threads = []
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(5)
if __name__ == '__main__':
t1 = threading.Thread(target = task1, args = (2,))
t2 = threading.Thread(target = task2, args = (2,))
threads.append(t1)
threads.append(t2)
for t in threads:
t.setDaemon(True)
t.start()
t.join()
print ('Main Function End\t %s' % ctime())
执行结果如下:
root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 21:18:05 2016
Func2 Task --- No.0 start at Sat Aug 13 21:18:05 2016
Func1 Task --- No.1 start at Sat Aug 13 21:18:08 2016
Func2 Task --- No.1 start at Sat Aug 13 21:18:10 2016
Main Function End Sat Aug 13 21:18:15 2016
由此可以看到,setDaemon只是为了设置主程序是否要退出程序,而join()函数则是为了将程序阻塞到这里,阻止主程序的继续执行,从而实现阻塞主线程,等待子线程执行完之后才执行之后代码的功能。
另外,The for-loop makes assignments to the variable(s) in the target list.
This overwrites all previous assignments to those variables including those made in the suite of the for-loop.
The target list is not deleted when the loop is finished.
But if the sequence is empty, they will not have been assigned to at all the loop.
也就是说for循环中的target list(for x in range(10) x 就是target list)在循环结束中并未被删除,可以被后续程序直接使用。但除一种情况外:循环序列为空时,target list根本不会被赋值。
这个根源还在于,Python中的for循环并没有引入作用域(scope)的概念,但函数定义有引入作用域。 什么意思呢? 如果你希望for循环变量不被其他程序误用/覆盖等,可以把for循环单独放在一个函数内。
可以在Ipython中进行实验,
for i in range(10):
pass
print i
可以看到打印的i显示i的值是9
#coding = utf-8
from time import ctime,time,sleep
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(2)
if __name__ == '__main__':
task1(2)
task2(2)
print ('Main Function End %s' % ctime())
● 打印结果
● root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 19:51:08 2016
Func1 Task --- No.1 start at Sat Aug 13 19:51:11 2016
Func2 Task --- No.0 start at Sat Aug 13 19:51:14 2016
Func2 Task --- No.1 start at Sat Aug 13 19:51:16 2016
Main Function End Sat Aug 13 19:51:18 2016
● 进阶版
引入threading.Thread,用两个线程进行程序执行
#coding = utf-8
import threading
from time import ctime,time,sleep
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(2)
if __name__ == '__main__':
t1 = threading.Thread(target = task1, args = (2,))
t2 = threading.Thread(target = task2, args = (2,))
t1.start()
t2.start()
print ('Main Function End\t %s' % ctime())
执行结果
root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 20:36:49 2016
Func2 Task --- No.0 start at Sat Aug 13 20:36:49 2016
Main Function End Sat Aug 13 20:36:49 2016
Func2 Task --- No.1 start at Sat Aug 13 20:36:51 2016
Func1 Task --- No.1 start at Sat Aug 13 20:36:52 2016
● 接下来观察一下daemon参数起什么作用
设置线程进行setDaemon()操作,讲daemon参数设置为True如下,观察结果:
#coding = utf-8
import threading
from time import ctime,time,sleep
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(2)
if __name__ == '__main__':
t1 = threading.Thread(target = task1, args = (2,))
t2 = threading.Thread(target = task2, args = (2,))
t1.setDaemon(True)
t2.setDaemon(True)
t1.start()
t2.start()
print ('Main Function End\t %s' % ctime())
这里需要注意的是,threading.Thread设置daemon参数必须在start()之前,不然程序会被无限挂起
root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 20:45:20 2016
Main Function End Sat Aug 13 20:45:20 2016
Func2 Task --- No.0 start at Sat Aug 13 20:45:20 2016
由此可见,t.setDaemon(True)的结果是:主线程在线程t结束之前就会随着主线程的结束而kill掉线程t,程序结束。
● 再玩一次:
#coding = utf-8
import threading
from time import ctime,time,sleep
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(5)
if __name__ == '__main__':
t1 = threading.Thread(target = task1, args = (2,))
t2 = threading.Thread(target = task2, args = (2,))
t1.setDaemon(False)
t2.setDaemon(True)
t1.start()
t2.start()
print ('Main Function End\t %s' % ctime())
● 那这样的话我就搞不懂了,为什么task2的第二条语句还是能打印出来?很令人费解……
由此推测setDaemon的作用是针对主线程的,用来设置主线程在执行完之后不能直接退出程序。
root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 21:03:57 2016
Func2 Task --- No.0 start at Sat Aug 13 21:03:57 2016
Main Function End Sat Aug 13 21:03:57 2016
Func1 Task --- No.1 start at Sat Aug 13 21:04:00 2016
Func2 Task --- No.1 start at Sat Aug 13 21:04:02 2016
通过以上执行结果,我们得知Python默认的daemon参数是False的,主线程会等到子线程执行完毕之后才会杀掉子线程结束程序。
● 故意将setDaemon放到start后面进行观察
#coding = utf-8
import threading
from time import ctime,time,sleep
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(2)
if __name__ == '__main__':
t1 = threading.Thread(target = task1, args = (2,))
t2 = threading.Thread(target = task2, args = (2,))
t1.start()
t2.start()
t1.setDaemon(False)
t2.setDaemon(True)
print ('Main Function End\t %s' % ctime())
执行结果如下:
root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 20:50:26 2016
Func2 Task --- No.0 start at Sat Aug 13 20:50:26 2016
Traceback (most recent call last):
File "threading_test.py", line 20, in <module>
t1.setDaemon(False)
File "/usr/lib/python2.7/threading.py", line 1036, in setDaemon
self.daemon = daemonic
File "/usr/lib/python2.7/threading.py", line 1029, in daemon
raise RuntimeError("cannot set daemon status of active thread");
RuntimeError: cannot set daemon status of active thread
Func2 Task --- No.1 start at Sat Aug 13 20:50:28 2016
Func1 Task --- No.1 start at Sat Aug 13 20:50:29 2016
瞧,主线程没有打印结果
● 加入join()观察一下结果:
#coding = utf-8
import threading
from time import ctime,time,sleep
threads = []
def task1(num):
for i in range(num):
print ('Func1 Task --- No.%d start at\t%s' %(i,ctime(time())))
sleep(3)
def task2(num):
for i in range(num):
print ('Func2 Task --- No.%d start at\t%s' % (i, ctime(time())))
sleep(5)
if __name__ == '__main__':
t1 = threading.Thread(target = task1, args = (2,))
t2 = threading.Thread(target = task2, args = (2,))
threads.append(t1)
threads.append(t2)
for t in threads:
t.setDaemon(True)
t.start()
t.join()
print ('Main Function End\t %s' % ctime())
执行结果如下:
root@root2:~/file_xlwu/f1/tmp# python threading_test.py
Func1 Task --- No.0 start at Sat Aug 13 21:18:05 2016
Func2 Task --- No.0 start at Sat Aug 13 21:18:05 2016
Func1 Task --- No.1 start at Sat Aug 13 21:18:08 2016
Func2 Task --- No.1 start at Sat Aug 13 21:18:10 2016
Main Function End Sat Aug 13 21:18:15 2016
由此可以看到,setDaemon只是为了设置主程序是否要退出程序,而join()函数则是为了将程序阻塞到这里,阻止主程序的继续执行,从而实现阻塞主线程,等待子线程执行完之后才执行之后代码的功能。
另外,The for-loop makes assignments to the variable(s) in the target list.
This overwrites all previous assignments to those variables including those made in the suite of the for-loop.
The target list is not deleted when the loop is finished.
But if the sequence is empty, they will not have been assigned to at all the loop.
也就是说for循环中的target list(for x in range(10) x 就是target list)在循环结束中并未被删除,可以被后续程序直接使用。但除一种情况外:循环序列为空时,target list根本不会被赋值。
这个根源还在于,Python中的for循环并没有引入作用域(scope)的概念,但函数定义有引入作用域。 什么意思呢? 如果你希望for循环变量不被其他程序误用/覆盖等,可以把for循环单独放在一个函数内。
可以在Ipython中进行实验,
for i in range(10):
pass
print i
可以看到打印的i显示i的值是9