- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
信息:
异常回溯如下
Exception ignored in: <bound method Connection.__del__ of <aiomysql.connection.Connection object at 0x00000030F8080B38>>
Traceback (most recent call last):
File "C:\software\development\python3.5\lib\site-packages\aiomysql\connection.py", line 689, in __del__
File "C:\software\development\python3.5\lib\site-packages\aiomysql\connection.py", line 261, in close
File "C:\software\development\python3.5\lib\asyncio\selector_events.py", line 569, in close
File "C:\software\development\python3.5\lib\asyncio\base_events.py", line 447, in call_soon
File "C:\software\development\python3.5\lib\asyncio\base_events.py", line 456, in _call_soon
File "C:\software\development\python3.5\lib\asyncio\base_events.py", line 284, in _check_closed
RuntimeError: Event loop is closed
我实现了一个简单的ORM框架,带有一些处理SQL的功能。orm.py中的一些相关代码(忽略中文注释)如下。类 Model 中的 update 或 findAll 方法运行良好,确实正确地给出了结果,但每次运行 test_method 后,它都会给出异常。
@asyncio.coroutine
def create_pool(loop, **kw): # 引入关键字后不用显示import asyncio了
# 该函数用于创建连接池
global __pool # 全局变量用于保存连接池
__pool = yield from aiomysql.create_pool(
host=kw.get('host', 'localhost'), # 默认定义host名字为localhost
port=kw.get('port', 3306), # 默认定义mysql的默认端口是3306
user=kw['user'], # user是通过关键字参数传进来的
password=kw['password'], # 密码也是通过关键字参数传进来的
db=kw['db'], # 数据库的名字
charset=kw.get('charset', 'utf8'), # 默认数据库字符集是utf8
autocommit=kw.get('autocommit', True), # 默认自动提交事务
maxsize=kw.get('maxsize', 10), # 连接池最多同时处理10个请求
minsize=kw.get('minsize', 1), # 连接池最少1个请求
loop=loop # 传递消息循环对象loop用于异步执行
)
@asyncio.coroutine
def execute(sql, args, autocommit=True):
# execute方法只返回结果数,不返回结果集,用于insert,update这些SQL语句
log(sql)
with (yield from __pool) as conn:
if not autocommit:
yield from conn.begin()
try:
cur = yield from conn.cursor()
# 执行sql语句,同时替换占位符
# pdb.set_trace()
yield from cur.execute(sql.replace('?', '%s'), args)
affected = cur.rowcount # 返回受影响的行数
yield from cur.close() # 关闭游标
if not autocommit:
yield from conn.commit()
except BaseException as e:
if not autocommit:
yield from conn.rollback()
raise e # raise不带参数,则把此处的错误往上抛;为了方便理解还是建议加e吧
return affected
class Model(dict, metaclass=ModelMetaclass):
# 继承dict是为了使用方便,例如对象实例user['id']即可轻松通过UserModel去数据库获取到id
# 元类自然是为了封装我们之前写的具体的SQL处理函数,从数据库获取数据
def __init__(self, **kw):
# 调用dict的父类__init__方法用于创建Model,super(类名,类对象)
super(Model, self).__init__(**kw)
def __getattr__(self, key):
# 调用不存在的属性时返回一些内容
try:
return self[key] # 如果存在则正常返回
except KeyError:
raise AttributeError(
r"'Model' object has no attribute '%s'" % key) # r表示不转义
def __setattr__(self, key, value):
# 设定Model里面的key-value对象,这里value允许为None
self[key] = value
def getValue(self, key):
# 获取某个具体的值,肯定存在的情况下使用该函数,否则会使用__getattr()__
# 获取实例的key,None是默认值,getattr方法使用可以参考http://kaimingwan.com/post/python/pythonzhong-de-nei-zhi-han-shu-getattr-yu-fan-she
return getattr(self, key, None)
def getValueOrDefault(self, key):
# 这个方法当value为None的时候能够返回默认值
value = getattr(self, key, None)
if value is None: # 不存在这样的值则直接返回
# self.__mapping__在metaclass中,用于保存不同实例属性在Model基类中的映射关系
field = self.__mappings__[key]
if field.default is not None: # 如果实例的域存在默认值,则使用默认值
# field.default是callable的话则直接调用
value = field.default() if callable(field.default) else field.default
logging.debug('using default value for %s:%s' %
(key, str(value)))
setattr(self, key, value)
return value
# --------------------------每个Model类的子类实例应该具备的执行SQL的方法比如save------
@classmethod # 类方法
@asyncio.coroutine
def findAll(cls, where=None, args=None, **kw):
sql = [cls.__select__] # 获取默认的select语句
if where: # 如果有where语句,则修改sql变量
# 这里不用协程,是因为不需要等待数据返回
sql.append('where') # sql里面加上where关键字
sql.append(where) # 这里的where实际上是colName='xxx'这样的条件表达式
if args is None: # 什么参数?
args = []
orderBy = kw.get('orderBy', None) # 从kw中查看是否有orderBy属性
if orderBy:
sql.append('order by')
sql.append(orderBy)
limit = kw.get('limit', None) # mysql中可以使用limit关键字
if limit is not None:
sql.append('limit')
if isinstance(limit, int): # 如果是int类型则增加占位符
sql.append('?')
args.append(limit)
elif isinstance(limit, tuple) and len(limit) == 2: # limit可以取2个参数,表示一个范围
sql.append('?,?')
args.extend(limit)
else: # 其他情况自然是语法问题
raise ValueError('Invalid limit value: %s' % str(limit))
# 在原来默认SQL语句后面再添加语句,要加个空格
rs = yield from select(' '.join(sql), args)
return [cls(**r) for r in rs] # 返回结果,结果是list对象,里面的元素是dict类型的
@classmethod
@asyncio.coroutine
def findNumber(cls, selectField, where=None, args=None):
# 获取行数
# 这里的 _num_ 什么意思?别名? 我估计是mysql里面一个记录实时查询结果条数的变量
sql = ['select %s _num_ from `%s`' % (selectField, cls.__table__)]
# pdb.set_trace()
if where:
sql.append('where')
sql.append(where) # 这里不加空格?
rs = yield from select(' '.join(sql), args, 1) # size = 1
if len(rs) == 0: # 结果集为0的情况
return None
return rs[0]['_num_'] # 有结果则rs这个list中第一个词典元素_num_这个key的value值
@classmethod
@asyncio.coroutine
def find_by_key(cls, pk):
# 根据主键查找
# pk是dict对象
rs = yield from select('%s where `%s`=?' % (cls.__select__, cls.__primary_key__), [pk], 1)
if len(rs) == 0:
return None
return cls(**rs[0])
# 这个是实例方法
@asyncio.coroutine
def save(self):
# arg是保存所有Model实例属性和主键的list,使用getValueOrDefault方法的好处是保存默认值
# 将自己的fields保存进去
args = list(map(self.getValueOrDefault, self.__fields__))
args.append(self.getValueOrDefault(self.__primary_key__))
# pdb.set_trace()
rows = yield from execute(self.__insert__, args) # 使用默认插入函数
if rows != 1:
# 插入失败就是rows!=1
logging.warn(
'failed to insert record: affected rows: %s' % rows)
@asyncio.coroutine
def update(self):
# 这里使用getValue说明只能更新那些已经存在的值,因此不能使用getValueOrDefault方法
args = list(map(self.getValue, self.__fields__))
args.append(self.getValue(self.__primary_key__))
# pdb.set_trace()
rows = yield from execute(self.__update__, args) # args是属性的list
if rows != 1:
logging.warn(
'failed to update by primary key: affected rows: %s' % rows)
@asyncio.coroutine
def remove(self):
args = [self.getValue(self.__primary_key__)]
# pdb.set_trace()
rows = yield from execute(self.__delete__, args)
if rows != 1:
logging.warn(
'failed to remove by primary key: affected rows: %s' % rows)
测试文件如下。
from models import User
import asyncio
import sys
import orm
import pdb
import time
# import pdb
# 测试插入
@asyncio.coroutine
def test_save(loop):
yield from orm.create_pool(loop, user='kami', password='kami', db='pure_blog')
u = User(name='hi', email='hi@example.com',
passwd='hi', image='about:blank')
# pdb.set_trace()
yield from u.save()
# 测试查询
@asyncio.coroutine
def test_findAll(loop):
yield from orm.create_pool(loop, user='kami', password='kami', db='pure_blog')
# 这里给的关键字参数按照xxx='xxx'的形式给出,会自动分装成dict
rs = yield from User.findAll(email='test@example.com') # rs是一个元素为dict的list
# pdb.set_trace()
for i in range(len(rs)):
print(rs[i])
# 查询条数?
@asyncio.coroutine
def test_findNumber(loop):
yield from orm.create_pool(loop, user='kami', password='kami', db='pure_blog')
count = yield from User.findNumber('email')
print(count)
# 根据主键查找,这里试ID
@asyncio.coroutine
def test_find_by_key(loop):
yield from orm.create_pool(loop, user='kami', password='kami', db='pure_blog')
# rs是一个dict
# ID请自己通过数据库查询
rs = yield from User.find_by_key('0014531826762080b29033a78624bc68c867550778f64d6000')
print(rs)
# 根据主键删除
@asyncio.coroutine
def test_remove(loop):
yield from orm.create_pool(loop, user='kami', password='kami', db='pure_blog')
# 用id初始化一个实例对象
u = User(id='0014531826762080b29033a78624bc68c867550778f64d6000')
yield from u.remove()
# 根据主键更新
@asyncio.coroutine
def test_update(loop):
yield from orm.create_pool(loop, user='kami', password='kami', db='pure_blog')
# 必须按照列的顺序来初始化:'update `users` set `created_at`=?, `passwd`=?, `image`=?,
# `admin`=?, `name`=?, `email`=? where `id`=?' 注意这里要使用time()方法,否则会直接返回个时间戳对象,而不是float值
u = User(id='00145318300622886f186530ee74afabecedb42f9cd590a000', created_at=time.time(), passwd='test',
image='about:blank', admin=True, name='test', email='hello1@example.com') # id必须和数据库一直,其他属性可以设置成新的值,属性要全
# pdb.set_trace()
yield from u.update()
loop = asyncio.get_event_loop() # 获取消息循环对象
loop.run_until_complete(test_update(loop)) # 执行协程
loop.close()
最佳答案
在关闭事件循环之前,需要关闭连接池,参见docs
pool.close()
yield from pool.wait_closed()
在你的情况下:
loop = asyncio.get_event_loop()
loop.run_until_complete(test_update(loop))
__pool.close()
loop.run_until_complete(__pool.wait_closed())
loop.close()
关于python - 为什么我在 python 3.5 中使用 asyncio 时会忽略异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34873111/
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!