我想使用 SQLAlchemy 和 Tornado 将货币 API 的输出保存在 MySQL 表中,但是当我循环 API 返回的 JSON 结果并将每个结果插入数据库时,应用程序陷入困境。当发生这种情况时,在所有插入完成之前不能执行其他过程。
我想我也应该将插入作为协程执行,但不知道该怎么做。我知道有几个用于异步 SQLAlchemy 的库,例如 Asyncio但使用 Tornado 时真的需要它们吗?
下面的代码在执行底部循环和Currency_rate时会阻塞
from datetime import datetime
from decimal import Decimal
import urllib
import tornado.web
import tornado.httpclient
from tornado import gen
from src.entities.currency import list_currencies, view_iso_a3_currency
from src.entities.currency_rate import Currency_rate
@gen.coroutine
def currencylayer_currency_rate():
http_client = tornado.httpclient.AsyncHTTPClient()
base_url = "http://apilayer.net/api/live?"
base_currency = view_iso_a3_currency('USD')
vars = {'access_key': 'APIKEY', 'source': base_currency.iso_a3, 'format': 1}
url = base_url + urllib.parse.urlencode(vars)
response = yield http_client.fetch(url)
if response.error:
raise tornado.web.HTTPError(500)
json = tornado.escape.json_decode(response.body)
timestamp = datetime.fromtimestamp(int(json['timestamp'])).strftime('%Y-%m-%d %H:%M:%S')
json_rates = json['quotes']
for key, value in json_rates.items():
quote_currency = view_iso_a3_currency(str(key)[-3:])
if not quote_currency:
continue
currency_rate = Currency_rate(m_currency_id1 = base_currency.id,
m_currency_id2 = quote_currency.id,
rate = Decimal(value),
date = timestamp,
create_user = 1,
update_user = 1,
active = 1)
currency_rate.add()
最佳答案
不幸的是,SQLAlchemy 不是异步的,对数据库的每个请求(操作)都会阻塞。更重要的是,ORM 的概念很难让它异步工作(引用: How to make SQLAlchemy in Tornado to be async? )。
您可能对项目(异步)感兴趣:
- momoko - 基于 postgres Tornado 的客户端,它不是 ORM,
- aiopg - postgres asyncio基于客户端(Tornado 4.3 及更高版本),支持 sqlalchemy 查询构建器
- tornado-mysql - 基于 MySQL Tornado 的客户端
提示:
response = yield http_client.fetch(url)
if response.error:
raise tornado.web.HTTPError(500)
yield 也会在出错时引发 HTTPError,因此不需要显式引发。
关于python - 使用 SQLAlchemy 和 Tornado 异步保存 API 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34162915/