threading.local函数可以创建线程本地数据空间,其下属性对每个线程独立存在,
先看一段代码
import threading
import time
# 本地线程对象
local_values = threading.local()
def func(num):
"""
# 第一个线程进来,本地线程对象会为他创建一个唯一标识
# 第二个线程进来,本地线程对象会为他创建一个唯一标识
{
线程1的唯一标识:{name:1},
线程2的唯一标识:{name:2},
}
:param num:
:return:
"""
local_values.name = num # 4
# 线程停下来了
time.sleep(2)
# 第二个线程: local_values.name,去local_values中根据自己的唯一标识作为key,获取value中name对应的值
print(local_values.name, threading.current_thread().name)
for i in range(5):
th = threading.Thread(target=func, args=(i,), name='线程%s' % i)
th.start()
以DButils为例
from DBUtils.PersistentDB import PersistentDB
import pymysql
POOL = PersistentDB(
creator=pymysql, # 使用链接数据库的模块
maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
ping=0,
# ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
closeable=False,
# 如果为False时, conn.close() 实际上被忽略,供下次使用,再线程关闭时,才会自动关闭链接。如果为True时, conn.close()则关闭链接,那么再次调用pool.connection时就会报错,因为已经真的关闭了连接(pool.steady_connection()可以获取一个新的链接)
threadlocal=None, # 本线程独享值得对象,用于保存链接对象,如果链接对象被重置
host='127.0.0.1',
port=3306,
user='root',
password='123',
database='pooldb',
charset='utf8'
)
看一下init方法
class PersistentDB:
"""
After you have created the connection pool, you can use
connection() to get thread-affine, steady DB-API 2 connections.
"""
version = __version__
def __init__(self, creator,
maxusage=None, setsession=None, failures=None, ping=1,
closeable=False, threadlocal=None, *args, **kwargs):
try:
threadsafety = creator.threadsafety
except AttributeError:
try:
if not callable(creator.connect):
raise AttributeError
except AttributeError:
threadsafety = 1
else:
threadsafety = 0
if not threadsafety:
raise NotSupportedError("Database module is not thread-safe.")
self._creator = creator
self._maxusage = maxusage
self._setsession = setsession
self._failures = failures
self._ping = ping
self._closeable = closeable
self._args, self._kwargs = args, kwargs
self.thread = (threadlocal or local)() #拿到本地线程对象
def steady_connection(self):
"""Get a steady, non-persistent DB-API 2 connection."""
return connect(
self._creator, self._maxusage, self._setsession,
self._failures, self._ping, self._closeable,
*self._args, **self._kwargs)
def connection(self, shareable=False):
"""Get a steady, persistent DB-API 2 connection.
The shareable parameter exists only for compatibility with the
PooledDB connection method. In reality, persistent connections
are of course never shared with other threads.
"""
try:
con = self.thread.connection
except AttributeError:
con = self.steady_connection()
if not con.threadsafety():
raise NotSupportedError("Database module is not thread-safe.")
self.thread.connection = con # 将创建的连接存储在本地线程对象中
con._ping_check()
return con