(一)终止线程
前一阵做GUI一些按钮功能耗时较长,会导致GUI无响应,所以把按钮功能放到了线程去做,有一个按钮点击后建立socket连接监听服务端的信息,再次点击按钮断开socket连接
于是就遇到了这个问题,使用线程开启的监听无法通过按钮退出线程,琢磨了一下想到一个办法,原先是用线程B启动socket任务,现在为了实现退出线程的功能,设置一个全局变量,然后使用线程A启动线程B,A启动B后每隔0.2s检查一下全局变量,当全局变量变化时退出线程,这样,B作为A的子线程也就会跟着退出,B线程启动时需要指定(thread.daemon = True)
PS:说下thread.daemon,当其为True时,父进(线)程退出子线程也跟着退出,这是默认值,当其为False时,父线程执行完毕后子线程不退出依旧运行,终端上运行的表现就是程序Ctrl+C不能终止程序
(二)跨文件全局变量
问题得到了解决,不过紧接着遇到了另一个问题。 当我把功能封装成模块后,子线程不能找到这个全局变量了,也就是说python中的全局变量是相对于文件来说的,跨文件就不行了
好在之前了解过python单例,下面是一个使用模块实现单例的例子
import sys
class Count(object):
def __init__(self):
print "init count"
self.a = 0
def up(self):
print "+1"
self.a = self.a + 1
def down(self):
print "-1"
self.a = self.a - 1
sys.modules[__name__] = Count()
''' python使用模块实现单例模式 '''
# 使用方法如下:
# [GCC 6.1.1 20160621 (Red Hat 6.1.1-3)] on linux2
# Type "help", "copyright", "credits" or "license" for more information.
# >>> import Count
# init count
# >>> Count.up()
# +1
# >>> Count.a
# 1
# >>> Count.up()
# +1
# >>> Count.a
# 2
# >>>
单例,只初始化一次,且不同文件导入的都是同一个对象,用法简单,正好可以完美解决多文件共享全局变量的问题,经过测试,证明了我的猜测
(三)Demo
.
├── global_flag.py
├── __init__.py
├── main.py
└── tools.py
0 directories, 4 files
main.py
#!/bin/env python
from tools import print_datetime, print_datetime_parent, \
print_datetime_with_thread
import global_flag
import time
def main():
'''
main function
'''
print_datetime_with_thread()
time.sleep(1)
print('execute me')
time.sleep(10)
print('main 10s after')
global_flag.change()
if __name__ == '__main__':
main()
tools.py
# -*- coding: utf-8 -*-
from threading import Thread
from time import strftime
import time
import global_flag
def print_datetime():
while True:
print(strftime('[%Y-%m-%d %H:%M:%S]'))
time.sleep(1)
def print_datetime_parent():
thread = Thread(target=print_datetime)
thread.daemon = True
thread.start()
while True:
if global_flag.get():
return
time.sleep(0.2)
def print_datetime_with_thread():
thread = Thread(target=print_datetime_parent)
thread.daemon = True
thread.start()
global_flag.py
import sys
class global_flag(object):
def __init__(self):
self.flag_value = False
def get(self):
return self.flag_value
def change(self):
self.flag_value = not self.flag_value
sys.modules[__name__] = global_flag()
output
[2017-05-20 17:12:29]
execute me
[2017-05-20 17:12:30]
[2017-05-20 17:12:31]
[2017-05-20 17:12:32]
[2017-05-20 17:12:33]
[2017-05-20 17:12:34]
[2017-05-20 17:12:35]
[2017-05-20 17:12:36]
[2017-05-20 17:12:37]
[2017-05-20 17:12:38]
[2017-05-20 17:12:39]
main 10s after
这样,无论是定时任务,还是手动发送信号,只要在主程序中需要停止子线程的地方更改global_flag类中变量的状态,则负责控制子线程的线程就能获取到信号,停止子线程