AttributeError: 'NoneType' object has no attribute 'read'还有AttributeError: 'NoneType' object has no attribute 'settimeout'还有TypeError: 'bool' object is not iterable等等,各类奇葩的错误。
好好的程序,前段页面同时发送了两个ajax请求,后端获取数据库数据就报错,经过不断的尝试,发现屏蔽任何一个ajax请求都没问题,只要同时发送两个就会报错,获取不到数据库数据,怀疑是数据库多线程访问加锁导致的,经上网搜索可能是以下的原因:
连接数据库用的是单例模式,访问请求使用了多线程,后台多线程共享了同一个数据库连接,但是数据库连接的每个execute前没有加上互斥锁就会报错:
AttributeError: 'NoneType' object has no attribute 'read'
错误原因:不详
尝试将数据库的单例连接修改为连接池连接,完美解决,不再
import logging import threading from queue import Queue, Empty __version__ = '0.1' __author__ = 'Chris' logger = logging.getLogger('pymysqlpool') __all__ = ['PoolContainer', 'PoolIsEmptyException', 'PoolIsFullException'] class PoolIsFullException(Exception): pass class PoolIsEmptyException(Exception): pass class PoolContainer(object): """ Pool container class: it's a pool manager with safe threading locks. Be aware of the dead lock!!!!!!!!!!! """ def __init__(self, max_pool_size): self._pool_lock = threading.RLock() self._free_items = Queue() # self._pool_items = list() self._pool_items = set() self._max_pool_size = 0 self.max_pool_size = max_pool_size def __repr__(self): return '<{0.__class__.__name__} {0.size})>'.format(self) def __iter__(self): with self._pool_lock: return iter(self._pool_items) def __contains__(self, item): with self._pool_lock: return item in self._pool_items def __len__(self): with self._pool_lock: return len(self._pool_items) def add(self, item): """Add a new item to the pool""" # Duplicate item will be ignored if item is None: return None if item in self: logger.debug( 'Duplicate item found "{}", ' 'current size is "{}"'.format(item, self.size)) return None if self.pool_size >= self.max_pool_size: raise PoolIsFullException() self._free_items.put_nowait(item) with self._pool_lock: # self._pool_items.append(item) self._pool_items.add(item) logger.debug( 'Add item "{!r}",' ' current size is "{}"'.format(item, self.size)) def return_(self, item): """Return a item to the pool. Note that the item to be returned should exist in this pool""" if item is None: return False if item not in self: logger.error( 'Current pool dose not contain item: "{}"'.format(item)) return False self._free_items.put_nowait(item) logger.debug('Return item "{!r}", current size is "{}"'.format(item, self.size)) return True def get(self, block=True, wait_timeout=60): """Block until a free item is found in `wait_timeout` seconds. Otherwise, a `WaitTimeoutException` will be raised. If `wait_timeout` is None, it will block forever until a free item is found. """ try: item = self._free_items.get(block, timeout=wait_timeout) except Empty: raise PoolIsEmptyException('Cannot find any available item') else: logger.debug('Get item "{}",' ' current size is "{}"'.format(item, self.size)) return item @property def size(self): # Return a tuple of the pool size in detail return '<max={}, current={}, free={}>'.format(self.max_pool_size, self.pool_size, self.free_size) @property def max_pool_size(self): return self._max_pool_size @max_pool_size.setter def max_pool_size(self, value): if value > self._max_pool_size: self._max_pool_size = value @property def pool_size(self): return len(self) @property def free_size(self): """Not reliable as described in document of the `queue` module""" return self._free_items.qsize()