我有一个非常小的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一样,它在运行时,但不是在它被测试时。但在另一个系统上,我似乎是从实际应用程序中获取数组。
答案 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
覆盖它,从而改变运行和测试之间的行为。