使用SQLAlchemy和Tornado保存API输出异步

时间:2015-12-08 18:06:27

标签: python asynchronous sqlalchemy tornado

我想使用SQLAlchemy和Tornado将货币API的输出保存在MySQL表中但是当我循环JSON结果时,API返回并且我将每个API插入数据库,应用程序卡住了。在发生这种情况时,在完成所有插入之前,不能执行任何其他过程。

我想我也应该像协程一样执行插入,但不知道该怎么做。我知道有几个用于异步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()

1 个答案:

答案 0 :(得分:1)

不幸的是,SQLAlchemy不是异步的,每个db的请求(操作)都会阻塞。更重要的是,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)

产量也会在出错时引发HTTPError,因此显式加注是不必要的。