Flask将namedtuples作为dicts返回,但不是所有时间

时间:2017-11-04 02:42:03

标签: python flask

我有一个非常小的Flask应用程序看起来非常像这样:

Point = namedtuple('Point', ['lat', 'lng', 'alt'])

p1 = Point(38.897741, -77.036450, 20)


def create_app():
    app = flask.Flask(__name__)

    @app.route('/position')
    def position():
        return flask.jsonify({
            'vehicle': p1,
        })

    return app

它仅用于将位置数据提供给web ui。我期待Point namedtuple将呈现为JSON数组,但令我惊讶的是我得到了:

{
  "vehicle": {
    "alt": 20, 
    "lat": 38.897741, 
    "lng": -77.03645
  }
}

......你知道,那很好。我可以解决这个问题。但后来我写了一些单元测试,看起来像这样:

from unittest import TestCase
import json
import tupletest

class TupleTestTest(TestCase):
    def setUp(self):
        _app = tupletest.create_app()
        _app.config['TESTING'] = True
        self.app = _app.test_client()

    def test_position(self):
        rv = self.app.get('/position')
        assert rv.status_code == 200
        assert rv.mimetype == 'application/json'
        data = json.loads(rv.get_data())
        assert data['vehicle']['lat'] = 38.897741

......他们失败了,因为突然间我不是得到字典:

>       assert data['vehicle']['lat'] == 38.897741
E       TypeError: list indices must be integers, not str

事实上,如果在测试中我将返回值写入我所拥有的文件中:

{
  "vehicle": [
    38.897741,
    -77.03645,
    20
  ]
}

什么。

这里发生了什么?为了这个问题的目的,我甚至无法重现这一点;上面的单元测试呈现字典。和我的实际webapp一样,它在运行时,但不是在它被测试时。但在另一个系统上,我似乎是从实际应用程序中获取数组。

1 个答案:

答案 0 :(得分:3)

查看源代码,这是在烧瓶jsonify.py

# Use the same json implementation as itsdangerous on which we
# depend anyways.
from itsdangerous import json as _json

并在itstangerous.py中有:

try:
    import simplejson as json
except ImportError:
    import json

simplejson库有一个选项namedtuple_as_object,默认情况下已启用。

因此,当安装第三方simplejson时,应用程序会使用它并将一个namedtuple序列化为一个JSON对象(Python中的一个dict)。

在未安装该库的系统上,该应用程序将回退到标准json并将一个namedtuple序列化为一个数组(列表)。

但是如果安装并导入simplejson,则测试程序直接导入标准json覆盖它,从而改变运行和测试之间的行为。