作用:同一个进程空间并发运行多个操作,专业术语简称为:【多线程】
1、任务函数不带参数多线程

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
def worker():
print('worker...')
threads = []
for i in range(3):
task = threading.Thread(target=worker)
threads.append(task)
task.start()
print(threads)
运行效果
[root@ mnt]# python3 threading_simple.py worker... worker... worker... [<Thread(Thread-1, stopped 140040860006144)>, <Thread(Thread-2, stopped 140040860006144)>, <Thread(Thread-3, stopped 140040860006144)>]
2、任务函数带参数多线程

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
def worker(num):
print('worker %s...' % num)
threads = []
for i in range(3):
task = threading.Thread(target=worker, args=(i,))
threads.append(task)
task.start()
print(threads)
运行效果
[root@ mnt]# python3 threading_simple_args.py worker 0... worker 1... worker 2... [<Thread(Thread-1, stopped 140326829315840)>, <Thread(Thread-2, stopped 140326829315840)>, <Thread(Thread-3, stopped 140326829315840)>]
3、线程标识名字设置和获取

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import time
def worker():
print(threading.current_thread().getName(), 'Starting')
time.sleep(0.2)
print(threading.current_thread().getName(), 'Exiting')
def my_service():
print(threading.current_thread().getName(), 'Starting')
time.sleep(0.3)
print(threading.current_thread().getName(), 'Exiting')
my_service_task = threading.Thread(name='my_service', target=my_service)
worker_task = threading.Thread(name='worker', target=worker)
default_task = threading.Thread(target=worker) # 使用默认的名字Thread-1
my_service_task.start()
worker_task.start()
default_task.start()
运行效果
[root@ mnt]# python3 threading_name.py my_service Starting worker Starting Thread-1 Starting worker Exiting Thread-1 Exiting my_service Exiting
4、线程标识名字设置和获取,利用logging模块打印出来日志,调试一般不建议用print打印出来

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import time
import logging
def worker():
logging.debug('Starting')
time.sleep(0.2)
logging.debug('Exiting')
def my_service():
logging.debug('Starting')
time.sleep(0.3)
logging.debug('Exiting')
logging.basicConfig(
level=logging.DEBUG,
# 以下格式化,参考官方文档:https://docs.python.org/3/library/logging.html
format='[%(levelname)s] (%(thread)d) (%(threadName)-10s) %(message)s',
)
my_service_task = threading.Thread(name='my_service', target=my_service)
worker_task = threading.Thread(name='worker', target=worker)
default_task = threading.Thread(target=worker) # 使用默认的名字Thread-1
my_service_task.start()
worker_task.start()
default_task.start()
运行效果
[root@ mnt]# python3 threading_name_logging.py [DEBUG] (140555433457408) (my_service) Starting [DEBUG] (140555354896128) (worker ) Starting [DEBUG] (140555346503424) (Thread-1 ) Starting [DEBUG] (140555354896128) (worker ) Exiting [DEBUG] (140555346503424) (Thread-1 ) Exiting [DEBUG] (140555433457408) (my_service) Exiting
5、守护线程随着主程序退出而关闭线程

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import time
import logging
def daemon():
logging.debug('daemon Starting...')
time.sleep(0.2)
logging.debug('daemon Exiting...')
def non_daemon():
logging.debug('non_daemon Starting...')
logging.debug('non_daemon Exiting...')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s'
)
daemon_task = threading.Thread(name='daemon', target=daemon, daemon=True) #设置为首护线程
non_daemon_task = threading.Thread(name='non_daemon_task', target=non_daemon)
daemon_task.start()
non_daemon_task.start()
运行效果
[root@mnt]# python3 threading_daemon.py (daemon ) daemon Starting... (non_daemon_task) non_daemon Starting... (non_daemon_task) non_daemon Exiting... #由于守护线程还没有执行完,主进程已退出,守护线程即随之被终止,从而导致【daemon Exiting...】没打印出来
6、等待守护线程运行结束,才关闭主程序

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import time
import logging
def daemon():
logging.debug('daemon Starting...')
time.sleep(0.2)
logging.debug('daemon Exiting...')
def non_daemon():
logging.debug('non_daemon Starting...')
logging.debug('non_daemon Exiting...')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s'
)
daemon_task = threading.Thread(name='daemon', target=daemon, daemon=True) # 设置为首护线程
non_daemon_task = threading.Thread(name='non_daemon_task', target=non_daemon)
daemon_task.start()
non_daemon_task.start()
daemon_task.join()
non_daemon_task.join()
运行效果
[root@ mnt]# python3 threading_daemon_join.py (daemon ) daemon Starting... (non_daemon_task) non_daemon Starting... (non_daemon_task) non_daemon Exiting... (daemon ) daemon Exiting...#由于使用的join等待线程运行完成,才结束,所以【daemon Exiting...】可以打印出来
7、设置守护线程的超时时间,防止进入无限阻塞

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import time
import logging
def daemon():
logging.debug('daemon Starting...')
time.sleep(0.2)
logging.debug('daemon Exiting...')
def non_daemon():
logging.debug('non_daemon Starting...')
logging.debug('non_daemon Exiting...')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s'
)
daemon_task = threading.Thread(name='daemon', target=daemon, daemon=True) # 设置为首护线程
non_daemon_task = threading.Thread(name='non_daemon_task', target=non_daemon)
daemon_task.start()
non_daemon_task.start()
daemon_task.join(0.1) #设置的超时时间0.1秒,因为该任务的函数睡眠0.2s,所以没有运行完成,就已经超时,结束该守护线程
print('isAlive()', daemon_task.isAlive())
non_daemon_task.join()
运行效果
[root@ mnt]# python3 threading_daemon_join_timeout.py (daemon ) daemon Starting... (non_daemon_task) non_daemon Starting... (non_daemon_task) non_daemon Exiting... isAlive() True #这里是判断线程是否在运行,True表在线程还在运行
8、利用threading.enumerate()枚举的方法,设置守护线程等待运行完成

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import time
import logging
import random
def worker():
pause = random.randint(1, 5) / 10
logging.debug('睡眠 %0.2f 秒', pause)
time.sleep(pause)
logging.debug('worker 结束')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s'
)
for i in range(3):
task = threading.Thread(target=worker, daemon=True)
task.start()
main_thread = threading.main_thread()
for task_obj in threading.enumerate(): #threading.enumerate():返回当前运行守护线程的实例
if task_obj is main_thread:
continue
logging.debug('等待 %s', task_obj.getName())
task_obj.join()
运行效果
[root@ mnt]# python3 threading_enumerate.py (Thread-1 ) 睡眠 0.30 秒 (Thread-2 ) 睡眠 0.10 秒 (Thread-3 ) 睡眠 0.10 秒 (MainThread) 等待 Thread-1 (Thread-2 ) worker 结束 (Thread-3 ) worker 结束 (Thread-1 ) worker 结束 (MainThread) 等待 Thread-2 (MainThread) 等待 Thread-3
9、利用继承threading.Thread类,实现无参的多线程

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
class MyThread(threading.Thread):
def run(self):
logging.debug('运行...')
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
for i in range(5):
task = MyThread()
task.start()
运行效果
[root@ mnt]# [root@python-mysql mnt]# python3 threading_subclass.py (Thread-1 ) 运行... (Thread-2 ) 运行... (Thread-3 ) 运行... (Thread-4 ) 运行... (Thread-5 ) 运行...
10、利用继承threading.Thread类,实现有参的多线程

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
class MyThread(threading.Thread):
def __init__(self, group=None, target=None, name=None, daemon=None, args=(), kwargs=None):
super(MyThread, self).__init__(group=group, target=target, name=name, daemon=daemon)
self.args = args
self.kwargs = kwargs
def run(self):
logging.debug('运行...args : %s,kwargs : %s', self.args, self.kwargs)
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
for i in range(5):
task = MyThread(args=(i,), kwargs={'a': 'A', 'b': 'B'})
task.start()
运行效果
[root@ mnt]# python3 threading_subclass_args.py
(Thread-1 ) 运行...args : (0,),kwargs : {'a': 'A', 'b': 'B'}
(Thread-2 ) 运行...args : (1,),kwargs : {'a': 'A', 'b': 'B'}
(Thread-3 ) 运行...args : (2,),kwargs : {'a': 'A', 'b': 'B'}
(Thread-4 ) 运行...args : (3,),kwargs : {'a': 'A', 'b': 'B'}
(Thread-5 ) 运行...args : (4,),kwargs : {'a': 'A', 'b': 'B'}
11、定时器线程threading.Timer

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
import time
def delayed():
logging.debug('delayed运行...')
logging.basicConfig(
level=logging.DEBUG,
format="(%(threadName)-10s) %(message)s"
)
task_1 = threading.Timer(0.3, delayed)
task_1.setName('task_1')
task_2 = threading.Timer(0.3, delayed)
task_2.setName('task_2')
logging.debug('开始运行Timer')
task_1.start()
task_2.start()
logging.debug('取消前等待')
time.sleep(0.2)
logging.debug('取消 %s' % task_2.getName())
task_2.cancel()
logging.debug('取消完成')
运行效果
[root@ mnt]# python3 threading_timer.py (MainThread) 开始运行Timer (MainThread) 取消前等待 (MainThread) 取消 task_2 (MainThread) 取消完成 (task_1 ) delayed运行... #task_2已经被取消,所以没有运行
12、线程间信号相互传送threading.Event

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
import time
def wait_for_event(event_obj):
logging.debug('等待事件的开始')
event_is_set = event_obj.wait()
logging.debug('事件设置 %s' % event_is_set)
def wait_for_event_timeout(event_obj, timeout):
while not event_obj.is_set():
logging.debug('等待事件超时开始')
event_is_set = event_obj.wait(timeout)
if event_is_set:
logging.debug('处理事件')
else:
logging.debug('做其他工作')
logging.basicConfig(
level=logging.DEBUG,
format="(%(threadName)-10s) %(message)s"
)
event_obj = threading.Event()
task_1 = threading.Thread(
name='block',
target=wait_for_event,
args=(event_obj,)
)
task_1.start()
task_2 = threading.Thread(
name='nonblock',
target=wait_for_event_timeout,
args=(event_obj, 2)
)
task_2.start()
logging.debug('在呼叫前等待 Event.set()')
time.sleep(0.3)
event_obj.set()
logging.debug('事件已经设置')
运行效果
[root@ mnt]# python3 threading_event.py (block ) 等待事件的开始 (nonblock ) 等待事件超时开始 (MainThread) 在呼叫前等待 Event.set() (MainThread) 事件已经设置 (block ) 事件设置 True (nonblock ) 处理事件
13、控制资源访问_计数器_多线程加阻塞锁的示例

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
import time
import random
class Counter(object):
def __init__(self, start=0):
self.lock = threading.Lock()
self.value = start
def increment(self):
logging.debug('等待锁')
self.lock.acquire()
try:
logging.debug('获取锁')
self.value += 1
finally:
self.lock.release()
def worker(c):
for i in range(2):
pause = random.random()
logging.debug('睡眠 %0.02f', pause)
time.sleep(pause)
c.increment()
logging.debug('worker运行结束')
logging.basicConfig(
level=logging.DEBUG,
format="(%(threadName)-10s) %(message)s"
)
counter = Counter()
for i in range(2):
t = threading.Thread(target=worker, args=(counter,))
t.start()
logging.debug('等待线程worker运行结束')
main_thread = threading.main_thread()
for t in threading.enumerate():
if t is not main_thread:
t.join()
logging.debug('Counter: %d', counter.value)
运行效果
[root@mnt]# python3 threading_lock.py (Thread-1 ) 睡眠 0.36 (Thread-2 ) 睡眠 0.77 (MainThread) 等待线程worker运行结束 (Thread-1 ) 等待锁 (Thread-1 ) 获取锁 (Thread-1 ) 睡眠 0.43 (Thread-2 ) 等待锁 (Thread-2 ) 获取锁 (Thread-2 ) 睡眠 0.12 (Thread-1 ) 等待锁 (Thread-1 ) 获取锁 (Thread-1 ) worker运行结束 (Thread-2 ) 等待锁 (Thread-2 ) 获取锁 (Thread-2 ) worker运行结束 (MainThread) Counter: 4 #运行4次,所以显示4
14、控制资源访问_计数器_多线程非阻塞锁的示例

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
import time
def lock_holder(lock_obj):
logging.debug('lock_holder 开始')
while True:
lock_obj.acquire()
try:
logging.debug('Holding')
time.sleep(0.5)
finally:
logging.debug('Not Holding')
lock_obj.release()
time.sleep(0.5)
def worker(lock_obj):
logging.debug('worker 开始')
num_tries = 0
num_acquires = 0
while num_acquires < 3:
time.sleep(0.5)
logging.debug('尝试获取锁')
have_it = lock_obj.acquire(0) # 主要核心代码在这里,不断尝试获取锁,通过这个判断锁是否释放可以获取
try:
num_tries += 1
if have_it:
logging.debug('重试次数 %d: 得到锁', num_tries)
num_acquires += 1
else:
logging.debug('重试次数 %d: 没有得到锁', num_tries)
finally:
if have_it:
lock_obj.release()
logging.debug('获取锁一共尝试的 %d 次', num_tries)
logging.basicConfig(
level=logging.DEBUG,
format="(%(threadName)-10s) %(message)s"
)
lock = threading.Lock()
holder = threading.Thread(
target=lock_holder,
args=(lock,),
name='LockHolder',
daemon=True,
)
holder.start()
worker = threading.Thread(
target=worker,
args=(lock,),
name='Worker',
)
worker.start()
运行结果
[root@ mnt]# python3 threading_lock_nonblock.py (LockHolder) lock_holder 开始 (LockHolder) Holding (Worker ) worker 开始 (LockHolder) Not Holding (Worker ) 尝试获取锁 (Worker ) 重试次数 1: 得到锁 (LockHolder) Holding (Worker ) 尝试获取锁 (Worker ) 重试次数 2: 没有得到锁 (LockHolder) Not Holding (Worker ) 尝试获取锁 (Worker ) 重试次数 3: 得到锁 (LockHolder) Holding (Worker ) 尝试获取锁 (Worker ) 重试次数 4: 没有得到锁 (LockHolder) Not Holding (Worker ) 尝试获取锁 (Worker ) 重试次数 5: 得到锁 (Worker ) 获取锁一共尝试的 5 次 #尝试的次数是随机,这样子的好处,不会因为阻塞占有CPU资源
15、互斥锁

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
lock = threading.Lock()
print('第一个锁', lock.acquire())
print('第二个锁', lock.acquire(0))
运行效果
[root@ mnt]# python3 threading_lock_reacquire.py 第一个锁 True 第二个锁 False
16、同步锁

import threading
lock = threading.RLock()
print('第一个锁', lock.acquire())
print('第二个锁', lock.acquire(0))
运行效果
[root@ mnt]# python3 threading_rlock.py 第一个锁 True 第二个锁 True
17、利用with管理锁,无需每次都释放锁lock.release()

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
def worker_with(lock):
with lock:
logging.debug('当前运行是用with 获取锁')
def worker_no_with(lock):
lock.acquire()
try:
logging.debug('当前运行是用 lock.acquire() 获取锁')
finally:
lock.release()
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
lock = threading.Lock()
with_open_lock = threading.Thread(target=worker_with, args=(lock,))
no_with_open_lock = threading.Thread(target=worker_no_with, args=(lock,))
with_open_lock.start()
no_with_open_lock.start()
运行效果
[root@ mnt]# python3 threading_with_lock.py (Thread-1 ) 当前运行是用with 获取锁 (Thread-2 ) 当前运行是用 lock.acquire() 获取锁
18、利用threading.Condition(),实现线程同步,下面是生产者和消费者的示例

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
import time
def consumer(condition_obj):
"""消费者"""
logging.debug('消费者线程开启')
with condition_obj:
condition_obj.wait()
logging.debug('资源可供消费者使用。')
def producer(condition_obj):
"""生产者"""
logging.debug('生产者线程开启')
with condition_obj:
logging.debug('生产可用资源')
condition_obj.notifyAll()
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
condition_obj = threading.Condition()
# 消费者实例1
c1 = threading.Thread(
name='c1',
target=consumer,
args=(condition_obj,)
)
# 消费者实例1
c2 = threading.Thread(
name='c2',
target=consumer,
args=(condition_obj,)
)
# 生产者实例
p = threading.Thread(
name='p',
target=producer,
args=(condition_obj,)
)
c1.start()
time.sleep(0.2)
c2.start()
time.sleep(0.2)
p.start()
运行效果
[root@ mnt]# python3 threading_condition.py (c1 ) 消费者线程开启 (c2 ) 消费者线程开启 (p ) 生产者线程开启 (p ) 生产可用资源 (c1 ) 资源可供消费者使用。 (c2 ) 资源可供消费者使用。
19、线程同步threading.Barrier() ,作用:等待所有线程一起开启后,再全部一起执行主要的功能

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
import time
def worker(barrier):
logging.debug('当前线程名字: %s 与 %s 其他人一起等待后面的功能' % (threading.current_thread().name, barrier.n_waiting))
worker_id = barrier.wait()
logging.debug('%s 已经等待完毕 %s' % (threading.current_thread().name, worker_id))
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
NUM_THREADS = 3
barrier = threading.Barrier(NUM_THREADS)
threads = [
threading.Thread(
name='worker-%s' % i,
target=worker,
args=(barrier,)
) for i in range(NUM_THREADS)
] # 这里是实例化3个线程,[<Thread(worker-0, initial)>, <Thread(worker-1, initial)>, <Thread(worker-2, initial)>]
for thread_obj in threads:
logging.debug('%s 开启' % thread_obj.name)
thread_obj.start()
time.sleep(0.2)
for thread_obj in threads:
thread_obj.join()
运行效果
[root@ mnt]# python3 threading_barrier.py (MainThread) worker-0 开启 (worker-0 ) 当前线程名字: worker-0 与 0 其他人一起等待后面的功能 (MainThread) worker-1 开启 (worker-1 ) 当前线程名字: worker-1 与 1 其他人一起等待后面的功能 (MainThread) worker-2 开启 (worker-2 ) 当前线程名字: worker-2 与 2 其他人一起等待后面的功能 (worker-2 ) worker-2 已经等待完毕 2 (worker-0 ) worker-0 已经等待完毕 0 (worker-1 ) worker-1 已经等待完毕 1
20、线程同步barrier.abort()中断的操作,作用:等待所有线程运行后面的功能,然后对它进行中断的操作,使用停止运行

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
import time
def worker(barrier):
logging.debug('当前线程名字: %s 与 %s 其他人一起等待后面的功能' % (threading.current_thread().name, barrier.n_waiting))
try:
worker_id = barrier.wait()
except threading.BrokenBarrierError:
logging.debug('%s 中断', threading.current_thread().name)
else:
logging.debug('%s 已经等待完毕 %s' % (threading.current_thread().name, worker_id))
logging.basicConfig(
level=logging.DEBUG,
format='(%(threadName)-10s) %(message)s',
)
NUM_THREADS = 3
# barrier.abort()必须多加一个线程,所以这里需要加1
barrier = threading.Barrier(NUM_THREADS + 1)
threads = [
threading.Thread(
name='worker-%s' % i,
target=worker,
args=(barrier,)
) for i in range(NUM_THREADS)
] # 这里是实例化3个线程,[<Thread(worker-0, initial)>, <Thread(worker-1, initial)>, <Thread(worker-2, initial)>]
for thread_obj in threads:
logging.debug('%s 开启' % thread_obj.name)
thread_obj.start()
time.sleep(0.1)
#中断线程一起同步运行
barrier.abort()
for thread_obj in threads:
thread_obj.join()
运行效果
[root@ mnt]# python3 threading_barrier_abort.py (MainThread) worker-0 开启 (worker-0 ) 当前线程名字: worker-0 与 0 其他人一起等待后面的功能 (MainThread) worker-1 开启 (worker-1 ) 当前线程名字: worker-1 与 1 其他人一起等待后面的功能 (MainThread) worker-2 开启 (worker-2 ) 当前线程名字: worker-2 与 2 其他人一起等待后面的功能 (worker-0 ) worker-0 中断 (worker-1 ) worker-1 中断 (worker-2 ) worker-2 中断
21、threading.Semaphore(),自定义线程池

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
import logging
import time
class ActivePool(object):
"""活动池"""
def __init__(self):
self.active = []
self.lock = threading.Lock()
def makeActive(self, name):
"""获取一个锁,把活动的名字增加于列表中"""
with self.lock:
self.active.append(name)
logging.debug('运行:%s' % self.active)
def makeInactive(self, name):
with self.lock:
self.active.remove(name)
logging.debug('运行:%s', self.active)
def worker(semaphore_obj, pool):
logging.debug('正在等待加入池')
with semaphore_obj:
name = threading.current_thread().getName()
pool.makeActive(name)
time.sleep(0.1)
pool.makeInactive(name)
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s (%(threadName)-10s) %(message)s',
)
pool = ActivePool()
semaphore_obj = threading.Semaphore(2)
for i in range(4):
t = threading.Thread(
target=worker,
name=str(i),
args=(semaphore_obj, pool)
)
t.start()
运行效果
[root@ mnt]# python3 threading_semaphore.py 2019-12-08 15:31:47,387 (0 ) 正在等待加入池 2019-12-08 15:31:47,387 (0 ) 运行:['0'] 2019-12-08 15:31:47,388 (1 ) 正在等待加入池 2019-12-08 15:31:47,389 (1 ) 运行:['0', '1'] 2019-12-08 15:31:47,389 (2 ) 正在等待加入池 2019-12-08 15:31:47,390 (3 ) 正在等待加入池 2019-12-08 15:31:47,489 (0 ) 运行:['1'] 2019-12-08 15:31:47,491 (1 ) 运行:[] 2019-12-08 15:31:47,492 (2 ) 运行:['2'] 2019-12-08 15:31:47,494 (3 ) 运行:['2', '3'] 2019-12-08 15:31:47,593 (2 ) 运行:['3'] 2019-12-08 15:31:47,596 (3 ) 运行:[]
22、threading.local(),本地线程任务运行隔离

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
import threading
import logging
def show_value(local_obj):
try:
val = local_obj.value
except AttributeError:
logging.debug('值不存在')
else:
logging.debug('value=%s', val)
def worker(local_obj):
show_value(local_obj)
local_obj.value = random.randint(1, 100)
show_value(local_obj)
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s (%(threadName)-10s) %(message)s',
)
local_obj = threading.local()
# 第一次运行没有设置value值,会报AttributeError异常
show_value(local_obj)
# 第二次运行有设置value值,所以会显示出值
local_obj.value = 1000
show_value(local_obj)
for i in range(2):
t = threading.Thread(
target=worker,
args=(local_obj,),
)
t.start()
运行效果
[root@ mnt]# python3 threading_local.py 2019-12-08 16:23:17,696 (MainThread) 值不存在 2019-12-08 16:23:17,697 (MainThread) value=1000 2019-12-08 16:23:17,697 (Thread-1 ) 值不存在 2019-12-08 16:23:17,698 (Thread-1 ) value=26 2019-12-08 16:23:17,698 (Thread-2 ) 值不存在 2019-12-08 16:23:17,698 (Thread-2 ) value=39
23、threading.local(),本地线程任务运行隔离,初始化全局变量值

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
import threading
import logging
def show_value(local_obj):
try:
val = local_obj.value
except AttributeError:
logging.debug('值不存在')
else:
logging.debug('value=%s', val)
def worker(local_obj):
show_value(local_obj)
local_obj.value = random.randint(1, 100)
show_value(local_obj)
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s (%(threadName)-10s) %(message)s',
)
class MyLocal(threading.local):
def __init__(self, value, *args, **kwargs):
super(MyLocal, self).__init__(*args, **kwargs)
logging.debug('初始化值 %r', self)
self.value = value
local_obj = MyLocal(1000)
show_value(local_obj)
for i in range(2):
t = threading.Thread(
target=worker,
args=(local_obj,)
)
t.start()
测试效果
[root@ mnt]# python3 threading_local.default.py 2019-12-08 16:28:48,168 (MainThread) 初始化值 <__main__.MyLocal object at 0x7fe58b6e1408> 2019-12-08 16:28:48,168 (MainThread) value=1000 2019-12-08 16:28:48,169 (Thread-1 ) 初始化值 <__main__.MyLocal object at 0x7fe58b6e1408> 2019-12-08 16:28:48,169 (Thread-1 ) value=1000 2019-12-08 16:28:48,169 (Thread-1 ) value=11 2019-12-08 16:28:48,170 (Thread-2 ) 初始化值 <__main__.MyLocal object at 0x7fe58b6e1408> 2019-12-08 16:28:48,170 (Thread-2 ) value=1000 2019-12-08 16:28:48,170 (Thread-2 ) value=7
